]> git.ipfire.org Git - thirdparty/hostap.git/blame - tests/hwsim/test_ap_hs20.py
tests: Add update_identifier to one of the HS 2.0 test cases
[thirdparty/hostap.git] / tests / hwsim / test_ap_hs20.py
CommitLineData
93a06242 1# Hotspot 2.0 tests
2f37a66d 2# Copyright (c) 2013-2014, Jouni Malinen <j@w1.fi>
93a06242
JM
3#
4# This software may be distributed under the terms of the BSD license.
5# See README for more details.
6
7import time
8import subprocess
9import logging
c9aa4308 10logger = logging.getLogger()
efd43d85
JM
11import os.path
12import subprocess
93a06242
JM
13
14import hostapd
715bf904 15from wlantest import Wlantest
93a06242 16
d4058934
JM
17def hs20_ap_params(ssid="test-hs20"):
18 params = hostapd.wpa2_params(ssid=ssid)
93a06242
JM
19 params['wpa_key_mgmt'] = "WPA-EAP"
20 params['ieee80211w'] = "1"
21 params['ieee8021x'] = "1"
22 params['auth_server_addr'] = "127.0.0.1"
23 params['auth_server_port'] = "1812"
24 params['auth_server_shared_secret'] = "radius"
25 params['interworking'] = "1"
26 params['access_network_type'] = "14"
27 params['internet'] = "1"
28 params['asra'] = "0"
29 params['esr'] = "0"
30 params['uesa'] = "0"
31 params['venue_group'] = "7"
32 params['venue_type'] = "1"
33 params['venue_name'] = [ "eng:Example venue", "fin:Esimerkkipaikka" ]
34 params['roaming_consortium'] = [ "112233", "1020304050", "010203040506",
35 "fedcba" ]
36 params['domain_name'] = "example.com,another.example.com"
37 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]",
38 "0,another.example.com" ]
39 params['hs20'] = "1"
40 params['hs20_wan_metrics'] = "01:8000:1000:80:240:3000"
41 params['hs20_conn_capab'] = [ "1:0:2", "6:22:1", "17:5060:0" ]
42 params['hs20_operating_class'] = "5173"
43 params['anqp_3gpp_cell_net'] = "244,91"
44 return params
45
2f37a66d 46def interworking_select(dev, bssid, type=None, no_match=False, freq=None):
bbe86767 47 dev.dump_monitor()
2f37a66d
JM
48 freq_extra = " freq=" + freq if freq else ""
49 dev.request("INTERWORKING_SELECT" + freq_extra)
bbe86767
JM
50 ev = dev.wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH"],
51 timeout=15)
93a06242
JM
52 if ev is None:
53 raise Exception("Network selection timed out");
bbe86767
JM
54 if no_match:
55 if "INTERWORKING-NO-MATCH" not in ev:
56 raise Exception("Unexpected network match")
57 return
93a06242
JM
58 if "INTERWORKING-NO-MATCH" in ev:
59 raise Exception("Matching network not found")
2cdd91d8 60 if bssid and bssid not in ev:
93a06242 61 raise Exception("Unexpected BSSID in match")
bbe86767
JM
62 if type and "type=" + type not in ev:
63 raise Exception("Network type not recognized correctly")
93a06242 64
bbe86767
JM
65def 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")
efd43d85 71
bbe86767 72def hlr_auc_gw_available():
efd43d85
JM
73 if not os.path.exists("/tmp/hlr_auc_gw.sock"):
74 logger.info("No hlr_auc_gw available");
bbe86767 75 return False
efd43d85
JM
76 if not os.path.exists("../../hostapd/hlr_auc_gw"):
77 logger.info("No hlr_auc_gw available");
bbe86767
JM
78 return False
79 return True
efd43d85 80
bbe86767
JM
81def interworking_ext_sim_connect(dev, bssid, method):
82 dev.request("INTERWORKING_CONNECT " + bssid)
078683ac 83 interworking_ext_sim_auth(dev, method)
efd43d85 84
078683ac 85def interworking_ext_sim_auth(dev, method):
bbe86767 86 ev = dev.wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=15)
efd43d85
JM
87 if ev is None:
88 raise Exception("Network connected timed out")
bbe86767 89 if "(" + method + ")" not in ev:
efd43d85
JM
90 raise Exception("Unexpected EAP method selection")
91
bbe86767 92 ev = dev.wait_event(["CTRL-REQ-SIM"], timeout=15)
efd43d85
JM
93 if ev is None:
94 raise Exception("Wait for external SIM processing request timed out")
95 p = ev.split(':', 2)
96 if p[1] != "GSM-AUTH":
97 raise Exception("Unexpected CTRL-REQ-SIM type")
98 id = p[0].split('-')[3]
99 rand = p[2].split(' ')[0]
100
101 res = subprocess.check_output(["../../hostapd/hlr_auc_gw",
102 "-m",
103 "auth_serv/hlr_auc_gw.milenage_db",
104 "GSM-AUTH-REQ 232010000000000 " + rand])
105 if "GSM-AUTH-RESP" not in res:
106 raise Exception("Unexpected hlr_auc_gw response")
107 resp = res.split(' ')[2].rstrip()
108
bbe86767
JM
109 dev.request("CTRL-RSP-SIM-" + id + ":GSM-AUTH:" + resp)
110 ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
efd43d85
JM
111 if ev is None:
112 raise Exception("Connection timed out")
f4defd91 113
8fba2e5d
JM
114def interworking_connect(dev, bssid, method):
115 dev.request("INTERWORKING_CONNECT " + bssid)
078683ac 116 interworking_auth(dev, method)
8fba2e5d 117
078683ac 118def interworking_auth(dev, method):
8fba2e5d
JM
119 ev = dev.wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=15)
120 if ev is None:
121 raise Exception("Network connected timed out")
122 if "(" + method + ")" not in ev:
123 raise Exception("Unexpected EAP method selection")
124
125 ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
126 if ev is None:
127 raise Exception("Connection timed out")
128
715bf904
JM
129def check_probe_resp(wt, bssid_unexpected, bssid_expected):
130 if bssid_unexpected:
131 count = wt.get_bss_counter("probe_response", bssid_unexpected)
132 if count > 0:
133 raise Exception("Unexpected Probe Response frame from AP")
134
135 if bssid_expected:
136 count = wt.get_bss_counter("probe_response", bssid_expected)
137 if count == 0:
138 raise Exception("No Probe Response frame from AP")
139
2cdd91d8
JM
140def test_ap_anqp_sharing(dev, apdev):
141 """ANQP sharing within ESS and explicit unshare"""
142 bssid = apdev[0]['bssid']
143 params = hs20_ap_params()
144 params['hessid'] = bssid
145 hostapd.add_ap(apdev[0]['ifname'], params)
146
147 bssid2 = apdev[1]['bssid']
148 params = hs20_ap_params()
149 params['hessid'] = bssid
150 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]" ]
151 hostapd.add_ap(apdev[1]['ifname'], params)
152
2cdd91d8
JM
153 dev[0].hs20_enable()
154 id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
155 'password': "secret",
156 'domain': "example.com" })
157 logger.info("Normal network selection with shared ANQP results")
2f37a66d 158 interworking_select(dev[0], None, "home", freq="2412")
2cdd91d8
JM
159 dev[0].dump_monitor()
160
161 res1 = dev[0].get_bss(bssid)
162 res2 = dev[0].get_bss(bssid2)
163 if res1['anqp_nai_realm'] != res2['anqp_nai_realm']:
164 raise Exception("ANQP results were not shared between BSSes")
165
166 logger.info("Explicit ANQP request to unshare ANQP results")
167 dev[0].request("ANQP_GET " + bssid + " 263")
168 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
169 if ev is None:
170 raise Exception("ANQP operation timed out")
171
172 dev[0].request("ANQP_GET " + bssid2 + " 263")
173 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
174 if ev is None:
175 raise Exception("ANQP operation timed out")
176
177 res1 = dev[0].get_bss(bssid)
178 res2 = dev[0].get_bss(bssid2)
179 if res1['anqp_nai_realm'] == res2['anqp_nai_realm']:
180 raise Exception("ANQP results were not unshared")
181
cddc19e5
JM
182def test_ap_nai_home_realm_query(dev, apdev):
183 """NAI Home Realm Query"""
184 bssid = apdev[0]['bssid']
185 params = hs20_ap_params()
186 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]",
187 "0,another.example.org" ]
188 hostapd.add_ap(apdev[0]['ifname'], params)
189
190 dev[0].scan(freq="2412")
191 dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + bssid + " realm=example.com")
192 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
193 if ev is None:
194 raise Exception("ANQP operation timed out")
195 nai1 = dev[0].get_bss(bssid)['anqp_nai_realm']
196 dev[0].dump_monitor()
197
198 dev[0].request("ANQP_GET " + bssid + " 263")
199 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
200 if ev is None:
201 raise Exception("ANQP operation timed out")
202 nai2 = dev[0].get_bss(bssid)['anqp_nai_realm']
203
204 if len(nai1) >= len(nai2):
205 raise Exception("Unexpected NAI Realm list response lengths")
206 if "example.com".encode('hex') not in nai1:
207 raise Exception("Home realm not reported")
208 if "example.org".encode('hex') in nai1:
209 raise Exception("Non-home realm reported")
210 if "example.com".encode('hex') not in nai2:
211 raise Exception("Home realm not reported in wildcard query")
212 if "example.org".encode('hex') not in nai2:
213 raise Exception("Non-home realm not reported in wildcard query ")
214
715bf904
JM
215def test_ap_interworking_scan_filtering(dev, apdev):
216 """Interworking scan filtering with HESSID and access network type"""
217 bssid = apdev[0]['bssid']
218 params = hs20_ap_params()
219 ssid = "test-hs20-ap1"
220 params['ssid'] = ssid
221 params['hessid'] = bssid
222 hostapd.add_ap(apdev[0]['ifname'], params)
223
224 bssid2 = apdev[1]['bssid']
225 params = hs20_ap_params()
226 ssid2 = "test-hs20-ap2"
227 params['ssid'] = ssid2
228 params['hessid'] = bssid2
229 params['access_network_type'] = "1"
8175854e
JM
230 del params['venue_group']
231 del params['venue_type']
715bf904
JM
232 hostapd.add_ap(apdev[1]['ifname'], params)
233
715bf904
JM
234 dev[0].hs20_enable()
235
236 wt = Wlantest()
237 wt.flush()
238
239 logger.info("Check probe request filtering based on HESSID")
240
241 dev[0].request("SET hessid " + bssid2)
0589f401 242 dev[0].scan(freq="2412")
94a2dd0b 243 time.sleep(0.03)
715bf904
JM
244 check_probe_resp(wt, bssid, bssid2)
245
246 logger.info("Check probe request filtering based on access network type")
247
248 wt.clear_bss_counters(bssid)
249 wt.clear_bss_counters(bssid2)
250 dev[0].request("SET hessid 00:00:00:00:00:00")
251 dev[0].request("SET access_network_type 14")
0589f401 252 dev[0].scan(freq="2412")
94a2dd0b 253 time.sleep(0.03)
715bf904
JM
254 check_probe_resp(wt, bssid2, bssid)
255
256 wt.clear_bss_counters(bssid)
257 wt.clear_bss_counters(bssid2)
258 dev[0].request("SET hessid 00:00:00:00:00:00")
259 dev[0].request("SET access_network_type 1")
0589f401 260 dev[0].scan(freq="2412")
94a2dd0b 261 time.sleep(0.03)
715bf904
JM
262 check_probe_resp(wt, bssid, bssid2)
263
264 logger.info("Check probe request filtering based on HESSID and ANT")
265
266 wt.clear_bss_counters(bssid)
267 wt.clear_bss_counters(bssid2)
268 dev[0].request("SET hessid " + bssid)
269 dev[0].request("SET access_network_type 14")
0589f401 270 dev[0].scan(freq="2412")
94a2dd0b 271 time.sleep(0.03)
715bf904
JM
272 check_probe_resp(wt, bssid2, bssid)
273
274 wt.clear_bss_counters(bssid)
275 wt.clear_bss_counters(bssid2)
276 dev[0].request("SET hessid " + bssid2)
277 dev[0].request("SET access_network_type 14")
0589f401 278 dev[0].scan(freq="2412")
94a2dd0b 279 time.sleep(0.03)
715bf904
JM
280 check_probe_resp(wt, bssid, None)
281 check_probe_resp(wt, bssid2, None)
282
283 wt.clear_bss_counters(bssid)
284 wt.clear_bss_counters(bssid2)
285 dev[0].request("SET hessid " + bssid)
286 dev[0].request("SET access_network_type 1")
0589f401 287 dev[0].scan(freq="2412")
94a2dd0b 288 time.sleep(0.03)
715bf904
JM
289 check_probe_resp(wt, bssid, None)
290 check_probe_resp(wt, bssid2, None)
291
bbe86767
JM
292def test_ap_hs20_select(dev, apdev):
293 """Hotspot 2.0 network selection"""
294 bssid = apdev[0]['bssid']
295 params = hs20_ap_params()
296 params['hessid'] = bssid
297 hostapd.add_ap(apdev[0]['ifname'], params)
298
299 dev[0].hs20_enable()
2232edf8
JM
300 id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
301 'password': "secret",
302 'domain': "example.com" })
bbe86767
JM
303 interworking_select(dev[0], bssid, "home")
304
305 dev[0].remove_cred(id)
2232edf8
JM
306 id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
307 'password': "secret",
308 'domain': "no.match.example.com" })
2f37a66d 309 interworking_select(dev[0], bssid, "roaming", freq="2412")
bbe86767
JM
310
311 dev[0].set_cred_quoted(id, "realm", "no.match.example.com");
2f37a66d 312 interworking_select(dev[0], bssid, no_match=True, freq="2412")
bbe86767 313
4b572e3a
JM
314 bssid2 = apdev[1]['bssid']
315 params = hs20_ap_params()
316 params['nai_realm'] = [ "0,example.org,21" ]
317 params['hessid'] = bssid2
318 params['domain_name'] = "example.org"
319 hostapd.add_ap(apdev[1]['ifname'], params)
320 dev[0].remove_cred(id)
321 id = dev[0].add_cred_values({ 'realm': "example.org", 'username': "test",
322 'password': "secret",
323 'domain': "example.org" })
324 interworking_select(dev[0], bssid2, "home", freq="2412")
325
459e96cd
JM
326def hs20_simulated_sim(dev, ap, method):
327 bssid = ap['bssid']
328 params = hs20_ap_params()
329 params['hessid'] = bssid
330 params['anqp_3gpp_cell_net'] = "555,444"
331 params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org"
332 hostapd.add_ap(ap['ifname'], params)
333
459e96cd
JM
334 dev.hs20_enable()
335 dev.add_cred_values({ 'imsi': "555444-333222111", 'eap': method,
336 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"})
2f37a66d 337 interworking_select(dev, "home", freq="2412")
459e96cd
JM
338 interworking_connect(dev, bssid, method)
339 check_sp_type(dev, "home")
340
341def test_ap_hs20_sim(dev, apdev):
342 """Hotspot 2.0 with simulated SIM and EAP-SIM"""
343 if not hlr_auc_gw_available():
344 return "skip"
345 hs20_simulated_sim(dev[0], apdev[0], "SIM")
346
347def test_ap_hs20_aka(dev, apdev):
348 """Hotspot 2.0 with simulated USIM and EAP-AKA"""
349 if not hlr_auc_gw_available():
350 return "skip"
351 hs20_simulated_sim(dev[0], apdev[0], "AKA")
352
353def test_ap_hs20_aka_prime(dev, apdev):
354 """Hotspot 2.0 with simulated USIM and EAP-AKA'"""
355 if not hlr_auc_gw_available():
356 return "skip"
357 hs20_simulated_sim(dev[0], apdev[0], "AKA'")
358
bbe86767
JM
359def test_ap_hs20_ext_sim(dev, apdev):
360 """Hotspot 2.0 with external SIM processing"""
361 if not hlr_auc_gw_available():
362 return "skip"
363 bssid = apdev[0]['bssid']
364 params = hs20_ap_params()
365 params['hessid'] = bssid
366 params['anqp_3gpp_cell_net'] = "232,01"
367 params['domain_name'] = "wlan.mnc001.mcc232.3gppnetwork.org"
368 hostapd.add_ap(apdev[0]['ifname'], params)
369
370 dev[0].hs20_enable()
371 dev[0].request("SET external_sim 1")
2232edf8 372 dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM" })
2f37a66d 373 interworking_select(dev[0], "home", freq="2412")
bbe86767
JM
374 interworking_ext_sim_connect(dev[0], bssid, "SIM")
375 check_sp_type(dev[0], "home")
59f8a3c6
JM
376
377def test_ap_hs20_ext_sim_roaming(dev, apdev):
378 """Hotspot 2.0 with external SIM processing in roaming network"""
379 if not hlr_auc_gw_available():
380 return "skip"
381 bssid = apdev[0]['bssid']
382 params = hs20_ap_params()
383 params['hessid'] = bssid
384 params['anqp_3gpp_cell_net'] = "244,91;310,026;232,01;234,56"
385 params['domain_name'] = "wlan.mnc091.mcc244.3gppnetwork.org"
386 hostapd.add_ap(apdev[0]['ifname'], params)
387
388 dev[0].hs20_enable()
389 dev[0].request("SET external_sim 1")
2232edf8 390 dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM" })
2f37a66d 391 interworking_select(dev[0], "roaming", freq="2412")
59f8a3c6
JM
392 interworking_ext_sim_connect(dev[0], bssid, "SIM")
393 check_sp_type(dev[0], "roaming")
8fba2e5d
JM
394
395def test_ap_hs20_username(dev, apdev):
396 """Hotspot 2.0 connection in username/password credential"""
8fba2e5d
JM
397 bssid = apdev[0]['bssid']
398 params = hs20_ap_params()
399 params['hessid'] = bssid
400 hostapd.add_ap(apdev[0]['ifname'], params)
401
402 dev[0].hs20_enable()
2232edf8
JM
403 id = dev[0].add_cred_values({ 'realm': "example.com",
404 'username': "hs20-test",
405 'password': "password",
5f1e31cf
JM
406 'domain': "example.com",
407 'update_identifier': "1234" })
2f37a66d 408 interworking_select(dev[0], bssid, "home", freq="2412")
8fba2e5d
JM
409 interworking_connect(dev[0], bssid, "TTLS")
410 check_sp_type(dev[0], "home")
411
dcd68168
JM
412def eap_test(dev, ap, eap_params, method, user):
413 bssid = ap['bssid']
414 params = hs20_ap_params()
415 params['nai_realm'] = [ "0,example.com," + eap_params ]
416 hostapd.add_ap(ap['ifname'], params)
417
dcd68168
JM
418 dev.hs20_enable()
419 dev.add_cred_values({ 'realm': "example.com",
420 'username': user,
421 'password': "password" })
2f37a66d 422 interworking_select(dev, bssid, freq="2412")
dcd68168
JM
423 interworking_connect(dev, bssid, method)
424
425def test_ap_hs20_eap_peap_mschapv2(dev, apdev):
426 """Hotspot 2.0 connection with PEAP/MSCHAPV2"""
427 eap_test(dev[0], apdev[0], "25[3:26]", "PEAP", "user")
428
429def test_ap_hs20_eap_peap_gtc(dev, apdev):
430 """Hotspot 2.0 connection with PEAP/GTC"""
431 eap_test(dev[0], apdev[0], "25[3:6]", "PEAP", "user")
432
433def test_ap_hs20_eap_ttls_chap(dev, apdev):
434 """Hotspot 2.0 connection with TTLS/CHAP"""
435 eap_test(dev[0], apdev[0], "21[2:2]", "TTLS", "chap user")
436
437def test_ap_hs20_eap_ttls_mschap(dev, apdev):
438 """Hotspot 2.0 connection with TTLS/MSCHAP"""
439 eap_test(dev[0], apdev[0], "21[2:3]", "TTLS", "mschap user")
440
441def test_ap_hs20_eap_ttls_eap_mschapv2(dev, apdev):
442 """Hotspot 2.0 connection with TTLS/EAP-MSCHAPv2"""
443 eap_test(dev[0], apdev[0], "21[3:26]", "TTLS", "user")
444
445def test_ap_hs20_eap_fast_mschapv2(dev, apdev):
446 """Hotspot 2.0 connection with FAST/EAP-MSCHAPV2"""
447 eap_test(dev[0], apdev[0], "43[3:26]", "FAST", "user")
448
449def test_ap_hs20_eap_fast_gtc(dev, apdev):
450 """Hotspot 2.0 connection with FAST/EAP-GTC"""
451 eap_test(dev[0], apdev[0], "43[3:6]", "FAST", "user")
452
453def test_ap_hs20_eap_tls(dev, apdev):
454 """Hotspot 2.0 connection with EAP-TLS"""
455 bssid = apdev[0]['bssid']
456 params = hs20_ap_params()
457 params['nai_realm'] = [ "0,example.com,13[5:6]" ]
458 hostapd.add_ap(apdev[0]['ifname'], params)
459
dcd68168
JM
460 dev[0].hs20_enable()
461 dev[0].add_cred_values({ 'realm': "example.com",
462 'username': "certificate-user",
463 'ca_cert': "auth_serv/ca.pem",
464 'client_cert': "auth_serv/user.pem",
465 'private_key': "auth_serv/user.key"})
2f37a66d 466 interworking_select(dev[0], bssid, freq="2412")
dcd68168
JM
467 interworking_connect(dev[0], bssid, "TLS")
468
0aca5d13
JM
469def test_ap_hs20_nai_realms(dev, apdev):
470 """Hotspot 2.0 connection and multiple NAI realms and TTLS/PAP"""
471 bssid = apdev[0]['bssid']
472 params = hs20_ap_params()
473 params['hessid'] = bssid
474 params['nai_realm'] = [ "0,no.match.here;example.com;no.match.here.either,21[2:1][5:7]" ]
475 hostapd.add_ap(apdev[0]['ifname'], params)
476
0aca5d13
JM
477 dev[0].hs20_enable()
478 id = dev[0].add_cred_values({ 'realm': "example.com",
479 'username': "pap user",
480 'password': "password",
481 'domain': "example.com" })
2f37a66d 482 interworking_select(dev[0], bssid, "home", freq="2412")
0aca5d13
JM
483 interworking_connect(dev[0], bssid, "TTLS")
484 check_sp_type(dev[0], "home")
485
e209eb98
JM
486def test_ap_hs20_roaming_consortium(dev, apdev):
487 """Hotspot 2.0 connection based on roaming consortium match"""
488 bssid = apdev[0]['bssid']
489 params = hs20_ap_params()
490 params['hessid'] = bssid
491 hostapd.add_ap(apdev[0]['ifname'], params)
492
e209eb98
JM
493 dev[0].hs20_enable()
494 id = dev[0].add_cred_values({ 'realm': "example.com",
495 'username': "user",
496 'password': "password",
497 'domain': "example.com",
498 'roaming_consortium': "fedcba",
499 'eap': "PEAP" })
2f37a66d 500 interworking_select(dev[0], bssid, "home", freq="2412")
e209eb98
JM
501 interworking_connect(dev[0], bssid, "PEAP")
502 check_sp_type(dev[0], "home")
503
8fba2e5d
JM
504def test_ap_hs20_username_roaming(dev, apdev):
505 """Hotspot 2.0 connection in username/password credential (roaming)"""
8fba2e5d
JM
506 bssid = apdev[0]['bssid']
507 params = hs20_ap_params()
508 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]",
509 "0,roaming.example.com,21[2:4][5:7]",
510 "0,another.example.com" ]
511 params['domain_name'] = "another.example.com"
512 params['hessid'] = bssid
513 hostapd.add_ap(apdev[0]['ifname'], params)
514
515 dev[0].hs20_enable()
2232edf8
JM
516 id = dev[0].add_cred_values({ 'realm': "roaming.example.com",
517 'username': "hs20-test",
518 'password': "password",
519 'domain': "example.com" })
2f37a66d 520 interworking_select(dev[0], bssid, "roaming", freq="2412")
8fba2e5d
JM
521 interworking_connect(dev[0], bssid, "TTLS")
522 check_sp_type(dev[0], "roaming")
523
524def test_ap_hs20_username_unknown(dev, apdev):
525 """Hotspot 2.0 connection in username/password credential (no domain in cred)"""
8fba2e5d
JM
526 bssid = apdev[0]['bssid']
527 params = hs20_ap_params()
528 params['hessid'] = bssid
529 hostapd.add_ap(apdev[0]['ifname'], params)
530
531 dev[0].hs20_enable()
2232edf8
JM
532 id = dev[0].add_cred_values({ 'realm': "example.com",
533 'username': "hs20-test",
534 'password': "password" })
2f37a66d 535 interworking_select(dev[0], bssid, "unknown", freq="2412")
8fba2e5d
JM
536 interworking_connect(dev[0], bssid, "TTLS")
537 check_sp_type(dev[0], "unknown")
538
539def test_ap_hs20_username_unknown2(dev, apdev):
540 """Hotspot 2.0 connection in username/password credential (no domain advertized)"""
8fba2e5d
JM
541 bssid = apdev[0]['bssid']
542 params = hs20_ap_params()
543 params['hessid'] = bssid
544 del params['domain_name']
545 hostapd.add_ap(apdev[0]['ifname'], params)
546
547 dev[0].hs20_enable()
2232edf8
JM
548 id = dev[0].add_cred_values({ 'realm': "example.com",
549 'username': "hs20-test",
550 'password': "password",
551 'domain': "example.com" })
2f37a66d 552 interworking_select(dev[0], bssid, "unknown", freq="2412")
8fba2e5d
JM
553 interworking_connect(dev[0], bssid, "TTLS")
554 check_sp_type(dev[0], "unknown")
d1ba402f 555
483691bd
JM
556def test_ap_hs20_gas_while_associated(dev, apdev):
557 """Hotspot 2.0 connection with GAS query while associated"""
558 bssid = apdev[0]['bssid']
559 params = hs20_ap_params()
560 params['hessid'] = bssid
561 hostapd.add_ap(apdev[0]['ifname'], params)
562
483691bd
JM
563 dev[0].hs20_enable()
564 id = dev[0].add_cred_values({ 'realm': "example.com",
565 'username': "hs20-test",
566 'password': "password",
567 'domain': "example.com" })
2f37a66d 568 interworking_select(dev[0], bssid, "home", freq="2412")
483691bd
JM
569 interworking_connect(dev[0], bssid, "TTLS")
570
571 logger.info("Verifying GAS query while associated")
572 dev[0].request("FETCH_ANQP")
573 for i in range(0, 6):
574 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
575 if ev is None:
576 raise Exception("Operation timed out")
577
ee2caef3
JM
578def test_ap_hs20_gas_while_associated_with_pmf(dev, apdev):
579 """Hotspot 2.0 connection with GAS query while associated and using PMF"""
580 bssid = apdev[0]['bssid']
581 params = hs20_ap_params()
582 params['hessid'] = bssid
583 hostapd.add_ap(apdev[0]['ifname'], params)
584
585 bssid2 = apdev[1]['bssid']
586 params = hs20_ap_params()
587 params['hessid'] = bssid2
588 params['nai_realm'] = [ "0,no-match.example.org,13[5:6],21[2:4][5:7]" ]
589 hostapd.add_ap(apdev[1]['ifname'], params)
590
591 dev[0].hs20_enable()
592 dev[0].request("SET pmf 2")
593 id = dev[0].add_cred_values({ 'realm': "example.com",
594 'username': "hs20-test",
595 'password': "password",
596 'domain': "example.com" })
597 interworking_select(dev[0], bssid, "home", freq="2412")
598 interworking_connect(dev[0], bssid, "TTLS")
599
600 logger.info("Verifying GAS query while associated")
601 dev[0].request("FETCH_ANQP")
602 for i in range(0, 2 * 6):
603 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
604 if ev is None:
605 raise Exception("Operation timed out")
606
483691bd
JM
607def test_ap_hs20_gas_frag_while_associated(dev, apdev):
608 """Hotspot 2.0 connection with fragmented GAS query while associated"""
609 bssid = apdev[0]['bssid']
610 params = hs20_ap_params()
611 params['hessid'] = bssid
612 hostapd.add_ap(apdev[0]['ifname'], params)
613 hapd = hostapd.Hostapd(apdev[0]['ifname'])
614 hapd.set("gas_frag_limit", "50")
615
483691bd
JM
616 dev[0].hs20_enable()
617 id = dev[0].add_cred_values({ 'realm': "example.com",
618 'username': "hs20-test",
619 'password': "password",
620 'domain': "example.com" })
2f37a66d 621 interworking_select(dev[0], bssid, "home", freq="2412")
483691bd
JM
622 interworking_connect(dev[0], bssid, "TTLS")
623
624 logger.info("Verifying GAS query while associated")
625 dev[0].request("FETCH_ANQP")
626 for i in range(0, 6):
627 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
628 if ev is None:
629 raise Exception("Operation timed out")
630
6a0b4002
JM
631def test_ap_hs20_multiple_connects(dev, apdev):
632 """Hotspot 2.0 connection through multiple network selections"""
633 bssid = apdev[0]['bssid']
634 params = hs20_ap_params()
635 params['hessid'] = bssid
636 hostapd.add_ap(apdev[0]['ifname'], params)
637
638 dev[0].hs20_enable()
639 values = { 'realm': "example.com",
640 'username': "hs20-test",
641 'password': "password",
642 'domain': "example.com" }
643 id = dev[0].add_cred_values(values)
644
645 for i in range(0, 3):
646 logger.info("Starting Interworking network selection")
2f37a66d 647 dev[0].request("INTERWORKING_SELECT auto freq=2412")
6a0b4002
JM
648 while True:
649 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH",
650 "INTERWORKING-ALREADY-CONNECTED",
651 "CTRL-EVENT-CONNECTED"], timeout=15)
652 if ev is None:
653 raise Exception("Connection timed out")
654 if "INTERWORKING-NO-MATCH" in ev:
655 raise Exception("Matching AP not found")
656 if "CTRL-EVENT-CONNECTED" in ev:
657 break
658 if i == 2 and "INTERWORKING-ALREADY-CONNECTED" in ev:
659 break
660 if i == 0:
661 dev[0].request("DISCONNECT")
662 dev[0].dump_monitor()
663
664 networks = dev[0].list_networks()
665 if len(networks) > 1:
666 raise Exception("Duplicated network block detected")
667
b4264f8f
JM
668def test_ap_hs20_disallow_aps(dev, apdev):
669 """Hotspot 2.0 connection and disallow_aps"""
670 bssid = apdev[0]['bssid']
671 params = hs20_ap_params()
672 params['hessid'] = bssid
673 hostapd.add_ap(apdev[0]['ifname'], params)
674
675 dev[0].hs20_enable()
676 values = { 'realm': "example.com",
677 'username': "hs20-test",
678 'password': "password",
679 'domain': "example.com" }
680 id = dev[0].add_cred_values(values)
681
682 logger.info("Verify disallow_aps bssid")
683 dev[0].request("SET disallow_aps bssid " + bssid.translate(None, ':'))
684 dev[0].request("INTERWORKING_SELECT auto")
685 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=15)
686 if ev is None:
687 raise Exception("Network selection timed out")
688 dev[0].dump_monitor()
689
690 logger.info("Verify disallow_aps ssid")
691 dev[0].request("SET disallow_aps ssid 746573742d68733230")
2f37a66d 692 dev[0].request("INTERWORKING_SELECT auto freq=2412")
b4264f8f
JM
693 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=15)
694 if ev is None:
695 raise Exception("Network selection timed out")
696 dev[0].dump_monitor()
697
698 logger.info("Verify disallow_aps clear")
699 dev[0].request("SET disallow_aps ")
2f37a66d 700 interworking_select(dev[0], bssid, "home", freq="2412")
b4264f8f
JM
701
702 dev[0].request("SET disallow_aps bssid " + bssid.translate(None, ':'))
703 ret = dev[0].request("INTERWORKING_CONNECT " + bssid)
704 if "FAIL" not in ret:
705 raise Exception("INTERWORKING_CONNECT to disallowed BSS not rejected")
706
d1ba402f
JM
707def policy_test(dev, ap, values, only_one=True):
708 dev.dump_monitor()
19839f8e
JM
709 if ap:
710 logger.info("Verify network selection to AP " + ap['ifname'])
711 bssid = ap['bssid']
712 else:
713 logger.info("Verify network selection")
714 bssid = None
d1ba402f
JM
715 dev.hs20_enable()
716 id = dev.add_cred_values(values)
2f37a66d 717 dev.request("INTERWORKING_SELECT auto freq=2412")
19839f8e 718 events = []
d1ba402f
JM
719 while True:
720 ev = dev.wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH",
1965cc3a 721 "INTERWORKING-BLACKLISTED",
953a574d 722 "INTERWORKING-SELECTED"], timeout=15)
d1ba402f 723 if ev is None:
953a574d 724 raise Exception("Network selection timed out")
19839f8e 725 events.append(ev)
d1ba402f
JM
726 if "INTERWORKING-NO-MATCH" in ev:
727 raise Exception("Matching AP not found")
19839f8e 728 if bssid and only_one and "INTERWORKING-AP" in ev and bssid not in ev:
d1ba402f 729 raise Exception("Unexpected AP claimed acceptable")
953a574d 730 if "INTERWORKING-SELECTED" in ev:
19839f8e 731 if bssid and bssid not in ev:
953a574d 732 raise Exception("Selected incorrect BSS")
d1ba402f
JM
733 break
734
953a574d
JM
735 ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
736 if ev is None:
737 raise Exception("Connection timed out")
19839f8e 738 if bssid and bssid not in ev:
953a574d
JM
739 raise Exception("Connected to incorrect BSS")
740
d1ba402f 741 conn_bssid = dev.get_status_field("bssid")
19839f8e 742 if bssid and conn_bssid != bssid:
d1ba402f
JM
743 raise Exception("bssid information points to incorrect BSS")
744
745 dev.remove_cred(id)
746 dev.dump_monitor()
19839f8e 747 return events
d1ba402f 748
d355372c
JM
749def default_cred():
750 return { 'realm': "example.com",
751 'username': "hs20-test",
752 'password': "password" }
753
d1ba402f
JM
754def test_ap_hs20_req_roaming_consortium(dev, apdev):
755 """Hotspot 2.0 required roaming consortium"""
756 params = hs20_ap_params()
757 hostapd.add_ap(apdev[0]['ifname'], params)
758
759 params = hs20_ap_params()
760 params['ssid'] = "test-hs20-other"
761 params['roaming_consortium'] = [ "223344" ]
762 hostapd.add_ap(apdev[1]['ifname'], params)
763
d355372c
JM
764 values = default_cred()
765 values['required_roaming_consortium'] = "223344"
d1ba402f
JM
766 policy_test(dev[0], apdev[1], values)
767 values['required_roaming_consortium'] = "112233"
768 policy_test(dev[0], apdev[0], values)
d355372c
JM
769
770def test_ap_hs20_excluded_ssid(dev, apdev):
771 """Hotspot 2.0 exclusion based on SSID"""
772 params = hs20_ap_params()
773 hostapd.add_ap(apdev[0]['ifname'], params)
774
775 params = hs20_ap_params()
776 params['ssid'] = "test-hs20-other"
777 params['roaming_consortium'] = [ "223344" ]
778 hostapd.add_ap(apdev[1]['ifname'], params)
779
780 values = default_cred()
781 values['excluded_ssid'] = "test-hs20"
1965cc3a
JM
782 events = policy_test(dev[0], apdev[1], values)
783 ev = [e for e in events if "INTERWORKING-BLACKLISTED " + apdev[0]['bssid'] in e]
784 if len(ev) != 1:
785 raise Exception("Excluded network not reported")
d355372c 786 values['excluded_ssid'] = "test-hs20-other"
1965cc3a
JM
787 events = policy_test(dev[0], apdev[0], values)
788 ev = [e for e in events if "INTERWORKING-BLACKLISTED " + apdev[1]['bssid'] in e]
789 if len(ev) != 1:
790 raise Exception("Excluded network not reported")
d4058934
JM
791
792def test_ap_hs20_roam_to_higher_prio(dev, apdev):
793 """Hotspot 2.0 and roaming from current to higher priority network"""
794 bssid = apdev[0]['bssid']
795 params = hs20_ap_params(ssid="test-hs20-visited")
796 params['domain_name'] = "visited.example.org"
797 hostapd.add_ap(apdev[0]['ifname'], params)
798
799 dev[0].hs20_enable()
800 id = dev[0].add_cred_values({ 'realm': "example.com",
801 'username': "hs20-test",
802 'password': "password",
803 'domain': "example.com" })
804 logger.info("Connect to the only network option")
805 interworking_select(dev[0], bssid, "roaming", freq="2412")
806 dev[0].dump_monitor()
807 interworking_connect(dev[0], bssid, "TTLS")
808
809 logger.info("Start another AP (home operator) and reconnect")
810 bssid2 = apdev[1]['bssid']
811 params = hs20_ap_params(ssid="test-hs20-home")
812 params['domain_name'] = "example.com"
813 hostapd.add_ap(apdev[1]['ifname'], params)
814
815 dev[0].request("INTERWORKING_SELECT auto freq=2412")
816 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH",
817 "INTERWORKING-ALREADY-CONNECTED",
818 "CTRL-EVENT-CONNECTED"], timeout=15)
819 if ev is None:
820 raise Exception("Connection timed out")
821 if "INTERWORKING-NO-MATCH" in ev:
822 raise Exception("Matching AP not found")
823 if "INTERWORKING-ALREADY-CONNECTED" in ev:
824 raise Exception("Unexpected AP selected")
825 if bssid2 not in ev:
826 raise Exception("Unexpected BSSID after reconnection")
12c587a5
JM
827
828def test_ap_hs20_domain_suffix_match(dev, apdev):
829 """Hotspot 2.0 and domain_suffix_match"""
830 bssid = apdev[0]['bssid']
831 params = hs20_ap_params()
832 hostapd.add_ap(apdev[0]['ifname'], params)
833
834 dev[0].hs20_enable()
835 id = dev[0].add_cred_values({ 'realm': "example.com",
836 'username': "hs20-test",
837 'password': "password",
838 'domain': "example.com",
839 'domain_suffix_match': "w1.fi" })
840 interworking_select(dev[0], bssid, "home", freq="2412")
841 dev[0].dump_monitor()
842 interworking_connect(dev[0], bssid, "TTLS")
843 dev[0].request("REMOVE_NETWORK all")
844 dev[0].dump_monitor()
845
846 dev[0].set_cred_quoted(id, "domain_suffix_match", "no-match.example.com")
847 interworking_select(dev[0], bssid, "home", freq="2412")
848 dev[0].dump_monitor()
849 dev[0].request("INTERWORKING_CONNECT " + bssid)
850 ev = dev[0].wait_event(["CTRL-EVENT-EAP-TLS-CERT-ERROR"])
851 if ev is None:
852 raise Exception("TLS certificate error not reported")
853 if "Domain suffix mismatch" not in ev:
854 raise Exception("Domain suffix mismatch not reported")
078683ac 855
2253ea44
JM
856def test_ap_hs20_roaming_partner_preference(dev, apdev):
857 """Hotspot 2.0 and roaming partner preference"""
858 params = hs20_ap_params()
859 params['domain_name'] = "roaming.example.org"
860 hostapd.add_ap(apdev[0]['ifname'], params)
861
862 params = hs20_ap_params()
863 params['ssid'] = "test-hs20-other"
864 params['domain_name'] = "roaming.example.net"
865 hostapd.add_ap(apdev[1]['ifname'], params)
866
867 logger.info("Verify default vs. specified preference")
868 values = default_cred()
869 values['roaming_partner'] = "roaming.example.net,1,127,*"
870 policy_test(dev[0], apdev[1], values, only_one=False)
871 values['roaming_partner'] = "roaming.example.net,1,129,*"
872 policy_test(dev[0], apdev[0], values, only_one=False)
873
874 logger.info("Verify partial FQDN match")
875 values['roaming_partner'] = "example.net,0,0,*"
876 policy_test(dev[0], apdev[1], values, only_one=False)
877 values['roaming_partner'] = "example.net,0,255,*"
878 policy_test(dev[0], apdev[0], values, only_one=False)
879
19839f8e
JM
880def test_ap_hs20_max_bss_load(dev, apdev):
881 """Hotspot 2.0 and maximum BSS load"""
882 params = hs20_ap_params()
883 params['bss_load_test'] = "12:200:20000"
884 hostapd.add_ap(apdev[0]['ifname'], params)
885
886 params = hs20_ap_params()
887 params['ssid'] = "test-hs20-other"
888 params['bss_load_test'] = "5:20:10000"
889 hostapd.add_ap(apdev[1]['ifname'], params)
890
891 logger.info("Verify maximum BSS load constraint")
892 values = default_cred()
893 values['domain'] = "example.com"
894 values['max_bss_load'] = "100"
895 events = policy_test(dev[0], apdev[1], values, only_one=False)
896
897 ev = [e for e in events if "INTERWORKING-AP " + apdev[0]['bssid'] in e]
898 if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
899 raise Exception("Maximum BSS Load case not noticed")
900 ev = [e for e in events if "INTERWORKING-AP " + apdev[1]['bssid'] in e]
901 if len(ev) != 1 or "over_max_bss_load=1" in ev[0]:
902 raise Exception("Maximum BSS Load case reported incorrectly")
903
904 logger.info("Verify maximum BSS load does not prevent connection")
905 values['max_bss_load'] = "1"
906 events = policy_test(dev[0], None, values)
907
908 ev = [e for e in events if "INTERWORKING-AP " + apdev[0]['bssid'] in e]
909 if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
910 raise Exception("Maximum BSS Load case not noticed")
911 ev = [e for e in events if "INTERWORKING-AP " + apdev[1]['bssid'] in e]
912 if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
913 raise Exception("Maximum BSS Load case not noticed")
914
915def test_ap_hs20_max_bss_load2(dev, apdev):
916 """Hotspot 2.0 and maximum BSS load with one AP not advertising"""
917 params = hs20_ap_params()
918 params['bss_load_test'] = "12:200:20000"
919 hostapd.add_ap(apdev[0]['ifname'], params)
920
921 params = hs20_ap_params()
922 params['ssid'] = "test-hs20-other"
923 hostapd.add_ap(apdev[1]['ifname'], params)
924
925 logger.info("Verify maximum BSS load constraint with AP advertisement")
926 values = default_cred()
927 values['domain'] = "example.com"
928 values['max_bss_load'] = "100"
929 events = policy_test(dev[0], apdev[1], values, only_one=False)
930
931 ev = [e for e in events if "INTERWORKING-AP " + apdev[0]['bssid'] in e]
932 if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
933 raise Exception("Maximum BSS Load case not noticed")
934 ev = [e for e in events if "INTERWORKING-AP " + apdev[1]['bssid'] in e]
935 if len(ev) != 1 or "over_max_bss_load=1" in ev[0]:
936 raise Exception("Maximum BSS Load case reported incorrectly")
937
078683ac
JM
938def test_ap_hs20_multi_cred_sp_prio(dev, apdev):
939 """Hotspot 2.0 multi-cred sp_priority"""
940 if not hlr_auc_gw_available():
941 return "skip"
942 bssid = apdev[0]['bssid']
943 params = hs20_ap_params()
944 params['hessid'] = bssid
945 del params['domain_name']
946 params['anqp_3gpp_cell_net'] = "232,01"
947 hostapd.add_ap(apdev[0]['ifname'], params)
948
949 dev[0].hs20_enable()
950 dev[0].request("SET external_sim 1")
951 id1 = dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM",
952 'provisioning_sp': "example.com",
953 'sp_priority' :"1" })
954 id2 = dev[0].add_cred_values({ 'realm': "example.com",
955 'username': "hs20-test",
956 'password': "password",
957 'domain': "example.com",
958 'provisioning_sp': "example.com",
959 'sp_priority': "2" })
960 dev[0].dump_monitor()
961 dev[0].request("INTERWORKING_SELECT auto")
962 interworking_ext_sim_auth(dev[0], "SIM")
963 check_sp_type(dev[0], "unknown")
964 dev[0].request("REMOVE_NETWORK all")
965
966 dev[0].set_cred(id1, "sp_priority", "2")
967 dev[0].set_cred(id2, "sp_priority", "1")
968 dev[0].dump_monitor()
969 dev[0].request("INTERWORKING_SELECT auto")
970 interworking_auth(dev[0], "TTLS")
971 check_sp_type(dev[0], "unknown")
972
973def test_ap_hs20_multi_cred_sp_prio2(dev, apdev):
974 """Hotspot 2.0 multi-cred sp_priority with two BSSes"""
975 if not hlr_auc_gw_available():
976 return "skip"
977 bssid = apdev[0]['bssid']
978 params = hs20_ap_params()
979 params['hessid'] = bssid
980 del params['nai_realm']
981 del params['domain_name']
982 params['anqp_3gpp_cell_net'] = "232,01"
983 hostapd.add_ap(apdev[0]['ifname'], params)
984
985 bssid2 = apdev[1]['bssid']
986 params = hs20_ap_params()
987 params['ssid'] = "test-hs20-other"
988 params['hessid'] = bssid2
989 del params['domain_name']
990 del params['anqp_3gpp_cell_net']
991 hostapd.add_ap(apdev[1]['ifname'], params)
992
993 dev[0].hs20_enable()
994 dev[0].request("SET external_sim 1")
995 id1 = dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM",
996 'provisioning_sp': "example.com",
997 'sp_priority': "1" })
998 id2 = dev[0].add_cred_values({ 'realm': "example.com",
999 'username': "hs20-test",
1000 'password': "password",
1001 'domain': "example.com",
1002 'provisioning_sp': "example.com",
1003 'sp_priority': "2" })
1004 dev[0].dump_monitor()
1005 dev[0].request("INTERWORKING_SELECT auto")
1006 interworking_ext_sim_auth(dev[0], "SIM")
1007 check_sp_type(dev[0], "unknown")
1008 conn_bssid = dev[0].get_status_field("bssid")
1009 if conn_bssid != bssid:
1010 raise Exception("Connected to incorrect BSS")
1011 dev[0].request("REMOVE_NETWORK all")
1012
1013 dev[0].set_cred(id1, "sp_priority", "2")
1014 dev[0].set_cred(id2, "sp_priority", "1")
1015 dev[0].dump_monitor()
1016 dev[0].request("INTERWORKING_SELECT auto")
1017 interworking_auth(dev[0], "TTLS")
1018 check_sp_type(dev[0], "unknown")
1019 conn_bssid = dev[0].get_status_field("bssid")
1020 if conn_bssid != bssid2:
1021 raise Exception("Connected to incorrect BSS")