tests: Use disable_dgaf=1 for more coverage
[mech_eap.git] / tests / hwsim / test_ap_hs20.py
1 # Hotspot 2.0 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 time
8 import subprocess
9 import logging
10 logger = logging.getLogger()
11 import os
12 import os.path
13 import subprocess
14
15 import hostapd
16 from wlantest import Wlantest
17
18 def hs20_ap_params(ssid="test-hs20"):
19     params = hostapd.wpa2_params(ssid=ssid)
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 check_auto_select(dev, bssid):
48     dev.request("INTERWORKING_SELECT auto freq=2412")
49     ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
50     if ev is None:
51         raise Exception("Connection timed out")
52     if bssid not in ev:
53         raise Exception("Connected to incorrect network")
54     dev.request("REMOVE_NETWORK all")
55
56 def interworking_select(dev, bssid, type=None, no_match=False, freq=None):
57     dev.dump_monitor()
58     freq_extra = " freq=" + freq if freq else ""
59     dev.request("INTERWORKING_SELECT" + freq_extra)
60     ev = dev.wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH"],
61                         timeout=15)
62     if ev is None:
63         raise Exception("Network selection timed out");
64     if no_match:
65         if "INTERWORKING-NO-MATCH" not in ev:
66             raise Exception("Unexpected network match")
67         return
68     if "INTERWORKING-NO-MATCH" in ev:
69         raise Exception("Matching network not found")
70     if bssid and bssid not in ev:
71         raise Exception("Unexpected BSSID in match")
72     if type and "type=" + type not in ev:
73         raise Exception("Network type not recognized correctly")
74
75 def check_sp_type(dev, sp_type):
76     type = dev.get_status_field("sp_type")
77     if type is None:
78         raise Exception("sp_type not available")
79     if type != sp_type:
80         raise Exception("sp_type did not indicate home network")
81
82 def hlr_auc_gw_available():
83     if not os.path.exists("/tmp/hlr_auc_gw.sock"):
84         logger.info("No hlr_auc_gw available");
85         return False
86     if not os.path.exists("../../hostapd/hlr_auc_gw"):
87         logger.info("No hlr_auc_gw available");
88         return False
89     return True
90
91 def interworking_ext_sim_connect(dev, bssid, method):
92     dev.request("INTERWORKING_CONNECT " + bssid)
93     interworking_ext_sim_auth(dev, method)
94
95 def interworking_ext_sim_auth(dev, method):
96     ev = dev.wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=15)
97     if ev is None:
98         raise Exception("Network connected timed out")
99     if "(" + method + ")" not in ev:
100         raise Exception("Unexpected EAP method selection")
101
102     ev = dev.wait_event(["CTRL-REQ-SIM"], timeout=15)
103     if ev is None:
104         raise Exception("Wait for external SIM processing request timed out")
105     p = ev.split(':', 2)
106     if p[1] != "GSM-AUTH":
107         raise Exception("Unexpected CTRL-REQ-SIM type")
108     id = p[0].split('-')[3]
109     rand = p[2].split(' ')[0]
110
111     res = subprocess.check_output(["../../hostapd/hlr_auc_gw",
112                                    "-m",
113                                    "auth_serv/hlr_auc_gw.milenage_db",
114                                    "GSM-AUTH-REQ 232010000000000 " + rand])
115     if "GSM-AUTH-RESP" not in res:
116         raise Exception("Unexpected hlr_auc_gw response")
117     resp = res.split(' ')[2].rstrip()
118
119     dev.request("CTRL-RSP-SIM-" + id + ":GSM-AUTH:" + resp)
120     ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
121     if ev is None:
122         raise Exception("Connection timed out")
123
124 def interworking_connect(dev, bssid, method):
125     dev.request("INTERWORKING_CONNECT " + bssid)
126     interworking_auth(dev, method)
127
128 def interworking_auth(dev, method):
129     ev = dev.wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=15)
130     if ev is None:
131         raise Exception("Network connected timed out")
132     if "(" + method + ")" not in ev:
133         raise Exception("Unexpected EAP method selection")
134
135     ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
136     if ev is None:
137         raise Exception("Connection timed out")
138
139 def check_probe_resp(wt, bssid_unexpected, bssid_expected):
140     if bssid_unexpected:
141         count = wt.get_bss_counter("probe_response", bssid_unexpected)
142         if count > 0:
143             raise Exception("Unexpected Probe Response frame from AP")
144
145     if bssid_expected:
146         count = wt.get_bss_counter("probe_response", bssid_expected)
147         if count == 0:
148             raise Exception("No Probe Response frame from AP")
149
150 def test_ap_anqp_sharing(dev, apdev):
151     """ANQP sharing within ESS and explicit unshare"""
152     bssid = apdev[0]['bssid']
153     params = hs20_ap_params()
154     params['hessid'] = bssid
155     hostapd.add_ap(apdev[0]['ifname'], params)
156
157     bssid2 = apdev[1]['bssid']
158     params = hs20_ap_params()
159     params['hessid'] = bssid
160     params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]" ]
161     hostapd.add_ap(apdev[1]['ifname'], params)
162
163     dev[0].hs20_enable()
164     id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
165                                   'password': "secret",
166                                   'domain': "example.com" })
167     logger.info("Normal network selection with shared ANQP results")
168     interworking_select(dev[0], None, "home", freq="2412")
169     dev[0].dump_monitor()
170
171     res1 = dev[0].get_bss(bssid)
172     res2 = dev[0].get_bss(bssid2)
173     if res1['anqp_nai_realm'] != res2['anqp_nai_realm']:
174         raise Exception("ANQP results were not shared between BSSes")
175
176     logger.info("Explicit ANQP request to unshare ANQP results")
177     dev[0].request("ANQP_GET " + bssid + " 263")
178     ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
179     if ev is None:
180         raise Exception("ANQP operation timed out")
181
182     dev[0].request("ANQP_GET " + bssid2 + " 263")
183     ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
184     if ev is None:
185         raise Exception("ANQP operation timed out")
186
187     res1 = dev[0].get_bss(bssid)
188     res2 = dev[0].get_bss(bssid2)
189     if res1['anqp_nai_realm'] == res2['anqp_nai_realm']:
190         raise Exception("ANQP results were not unshared")
191
192 def test_ap_nai_home_realm_query(dev, apdev):
193     """NAI Home Realm Query"""
194     bssid = apdev[0]['bssid']
195     params = hs20_ap_params()
196     params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]",
197                             "0,another.example.org" ]
198     hostapd.add_ap(apdev[0]['ifname'], params)
199
200     dev[0].scan(freq="2412")
201     dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + bssid + " realm=example.com")
202     ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
203     if ev is None:
204         raise Exception("ANQP operation timed out")
205     nai1 = dev[0].get_bss(bssid)['anqp_nai_realm']
206     dev[0].dump_monitor()
207
208     dev[0].request("ANQP_GET " + bssid + " 263")
209     ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
210     if ev is None:
211         raise Exception("ANQP operation timed out")
212     nai2 = dev[0].get_bss(bssid)['anqp_nai_realm']
213
214     if len(nai1) >= len(nai2):
215         raise Exception("Unexpected NAI Realm list response lengths")
216     if "example.com".encode('hex') not in nai1:
217         raise Exception("Home realm not reported")
218     if "example.org".encode('hex') in nai1:
219         raise Exception("Non-home realm reported")
220     if "example.com".encode('hex') not in nai2:
221         raise Exception("Home realm not reported in wildcard query")
222     if "example.org".encode('hex') not in nai2:
223         raise Exception("Non-home realm not reported in wildcard query ")
224
225 def test_ap_interworking_scan_filtering(dev, apdev):
226     """Interworking scan filtering with HESSID and access network type"""
227     bssid = apdev[0]['bssid']
228     params = hs20_ap_params()
229     ssid = "test-hs20-ap1"
230     params['ssid'] = ssid
231     params['hessid'] = bssid
232     hostapd.add_ap(apdev[0]['ifname'], params)
233
234     bssid2 = apdev[1]['bssid']
235     params = hs20_ap_params()
236     ssid2 = "test-hs20-ap2"
237     params['ssid'] = ssid2
238     params['hessid'] = bssid2
239     params['access_network_type'] = "1"
240     del params['venue_group']
241     del params['venue_type']
242     hostapd.add_ap(apdev[1]['ifname'], params)
243
244     dev[0].hs20_enable()
245
246     wt = Wlantest()
247     wt.flush()
248
249     logger.info("Check probe request filtering based on HESSID")
250
251     dev[0].request("SET hessid " + bssid2)
252     dev[0].scan(freq="2412")
253     time.sleep(0.03)
254     check_probe_resp(wt, bssid, bssid2)
255
256     logger.info("Check probe request filtering based on access network type")
257
258     wt.clear_bss_counters(bssid)
259     wt.clear_bss_counters(bssid2)
260     dev[0].request("SET hessid 00:00:00:00:00:00")
261     dev[0].request("SET access_network_type 14")
262     dev[0].scan(freq="2412")
263     time.sleep(0.03)
264     check_probe_resp(wt, bssid2, bssid)
265
266     wt.clear_bss_counters(bssid)
267     wt.clear_bss_counters(bssid2)
268     dev[0].request("SET hessid 00:00:00:00:00:00")
269     dev[0].request("SET access_network_type 1")
270     dev[0].scan(freq="2412")
271     time.sleep(0.03)
272     check_probe_resp(wt, bssid, bssid2)
273
274     logger.info("Check probe request filtering based on HESSID and ANT")
275
276     wt.clear_bss_counters(bssid)
277     wt.clear_bss_counters(bssid2)
278     dev[0].request("SET hessid " + bssid)
279     dev[0].request("SET access_network_type 14")
280     dev[0].scan(freq="2412")
281     time.sleep(0.03)
282     check_probe_resp(wt, bssid2, bssid)
283
284     wt.clear_bss_counters(bssid)
285     wt.clear_bss_counters(bssid2)
286     dev[0].request("SET hessid " + bssid2)
287     dev[0].request("SET access_network_type 14")
288     dev[0].scan(freq="2412")
289     time.sleep(0.03)
290     check_probe_resp(wt, bssid, None)
291     check_probe_resp(wt, bssid2, None)
292
293     wt.clear_bss_counters(bssid)
294     wt.clear_bss_counters(bssid2)
295     dev[0].request("SET hessid " + bssid)
296     dev[0].request("SET access_network_type 1")
297     dev[0].scan(freq="2412")
298     time.sleep(0.03)
299     check_probe_resp(wt, bssid, None)
300     check_probe_resp(wt, bssid2, None)
301
302 def test_ap_hs20_select(dev, apdev):
303     """Hotspot 2.0 network selection"""
304     bssid = apdev[0]['bssid']
305     params = hs20_ap_params()
306     params['hessid'] = bssid
307     hostapd.add_ap(apdev[0]['ifname'], params)
308
309     dev[0].hs20_enable()
310     id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
311                                   'password': "secret",
312                                   'domain': "example.com" })
313     interworking_select(dev[0], bssid, "home")
314
315     dev[0].remove_cred(id)
316     id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
317                                   'password': "secret",
318                                   'domain': "no.match.example.com" })
319     interworking_select(dev[0], bssid, "roaming", freq="2412")
320
321     dev[0].set_cred_quoted(id, "realm", "no.match.example.com");
322     interworking_select(dev[0], bssid, no_match=True, freq="2412")
323
324     bssid2 = apdev[1]['bssid']
325     params = hs20_ap_params()
326     params['nai_realm'] = [ "0,example.org,21" ]
327     params['hessid'] = bssid2
328     params['domain_name'] = "example.org"
329     hostapd.add_ap(apdev[1]['ifname'], params)
330     dev[0].remove_cred(id)
331     id = dev[0].add_cred_values({ 'realm': "example.org", 'username': "test",
332                                   'password': "secret",
333                                   'domain': "example.org" })
334     interworking_select(dev[0], bssid2, "home", freq="2412")
335
336 def hs20_simulated_sim(dev, ap, method):
337     bssid = ap['bssid']
338     params = hs20_ap_params()
339     params['hessid'] = bssid
340     params['anqp_3gpp_cell_net'] = "555,444"
341     params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org"
342     hostapd.add_ap(ap['ifname'], params)
343
344     dev.hs20_enable()
345     dev.add_cred_values({ 'imsi': "555444-333222111", 'eap': method,
346                           'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"})
347     interworking_select(dev, "home", freq="2412")
348     interworking_connect(dev, bssid, method)
349     check_sp_type(dev, "home")
350
351 def test_ap_hs20_sim(dev, apdev):
352     """Hotspot 2.0 with simulated SIM and EAP-SIM"""
353     if not hlr_auc_gw_available():
354         return "skip"
355     hs20_simulated_sim(dev[0], apdev[0], "SIM")
356     dev[0].request("INTERWORKING_SELECT auto freq=2412")
357     ev = dev[0].wait_event(["INTERWORKING-ALREADY-CONNECTED"], timeout=15)
358     if ev is None:
359         raise Exception("Timeout on already-connected event")
360
361 def test_ap_hs20_aka(dev, apdev):
362     """Hotspot 2.0 with simulated USIM and EAP-AKA"""
363     if not hlr_auc_gw_available():
364         return "skip"
365     hs20_simulated_sim(dev[0], apdev[0], "AKA")
366
367 def test_ap_hs20_aka_prime(dev, apdev):
368     """Hotspot 2.0 with simulated USIM and EAP-AKA'"""
369     if not hlr_auc_gw_available():
370         return "skip"
371     hs20_simulated_sim(dev[0], apdev[0], "AKA'")
372
373 def test_ap_hs20_ext_sim(dev, apdev):
374     """Hotspot 2.0 with external SIM processing"""
375     if not hlr_auc_gw_available():
376         return "skip"
377     bssid = apdev[0]['bssid']
378     params = hs20_ap_params()
379     params['hessid'] = bssid
380     params['anqp_3gpp_cell_net'] = "232,01"
381     params['domain_name'] = "wlan.mnc001.mcc232.3gppnetwork.org"
382     hostapd.add_ap(apdev[0]['ifname'], params)
383
384     dev[0].hs20_enable()
385     dev[0].request("SET external_sim 1")
386     dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM" })
387     interworking_select(dev[0], "home", freq="2412")
388     interworking_ext_sim_connect(dev[0], bssid, "SIM")
389     check_sp_type(dev[0], "home")
390
391 def test_ap_hs20_ext_sim_roaming(dev, apdev):
392     """Hotspot 2.0 with external SIM processing in roaming network"""
393     if not hlr_auc_gw_available():
394         return "skip"
395     bssid = apdev[0]['bssid']
396     params = hs20_ap_params()
397     params['hessid'] = bssid
398     params['anqp_3gpp_cell_net'] = "244,91;310,026;232,01;234,56"
399     params['domain_name'] = "wlan.mnc091.mcc244.3gppnetwork.org"
400     hostapd.add_ap(apdev[0]['ifname'], params)
401
402     dev[0].hs20_enable()
403     dev[0].request("SET external_sim 1")
404     dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM" })
405     interworking_select(dev[0], "roaming", freq="2412")
406     interworking_ext_sim_connect(dev[0], bssid, "SIM")
407     check_sp_type(dev[0], "roaming")
408
409 def test_ap_hs20_username(dev, apdev):
410     """Hotspot 2.0 connection in username/password credential"""
411     bssid = apdev[0]['bssid']
412     params = hs20_ap_params()
413     params['hessid'] = bssid
414     params['disable_dgaf'] = '1'
415     hostapd.add_ap(apdev[0]['ifname'], params)
416
417     dev[0].hs20_enable()
418     id = dev[0].add_cred_values({ 'realm': "example.com",
419                                   'username': "hs20-test",
420                                   'password': "password",
421                                   'ca_cert': "auth_serv/ca.pem",
422                                   'domain': "example.com",
423                                   'update_identifier': "1234" })
424     interworking_select(dev[0], bssid, "home", freq="2412")
425     interworking_connect(dev[0], bssid, "TTLS")
426     check_sp_type(dev[0], "home")
427     status = dev[0].get_status()
428     if status['pairwise_cipher'] != "CCMP":
429         raise Exception("Unexpected pairwise cipher")
430     if status['hs20'] != "2":
431         raise Exception("Unexpected HS 2.0 support indication")
432
433     dev[1].connect("test-hs20", key_mgmt="WPA-EAP", eap="TTLS",
434                    identity="hs20-test", password="password",
435                    ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
436                    scan_freq="2412")
437
438 def eap_test(dev, ap, eap_params, method, user):
439     bssid = ap['bssid']
440     params = hs20_ap_params()
441     params['nai_realm'] = [ "0,example.com," + eap_params ]
442     hostapd.add_ap(ap['ifname'], params)
443
444     dev.hs20_enable()
445     dev.add_cred_values({ 'realm': "example.com",
446                           'username': user,
447                           'password': "password" })
448     interworking_select(dev, bssid, freq="2412")
449     interworking_connect(dev, bssid, method)
450
451 def test_ap_hs20_eap_unknown(dev, apdev):
452     """Hotspot 2.0 connection with unknown EAP method"""
453     bssid = apdev[0]['bssid']
454     params = hs20_ap_params()
455     params['nai_realm'] = "0,example.com,99"
456     hostapd.add_ap(apdev[0]['ifname'], params)
457
458     dev[0].hs20_enable()
459     dev[0].add_cred_values(default_cred())
460     interworking_select(dev[0], None, no_match=True, freq="2412")
461
462 def test_ap_hs20_eap_peap_mschapv2(dev, apdev):
463     """Hotspot 2.0 connection with PEAP/MSCHAPV2"""
464     eap_test(dev[0], apdev[0], "25[3:26]", "PEAP", "user")
465
466 def test_ap_hs20_eap_peap_default(dev, apdev):
467     """Hotspot 2.0 connection with PEAP/MSCHAPV2 (as default)"""
468     eap_test(dev[0], apdev[0], "25", "PEAP", "user")
469
470 def test_ap_hs20_eap_peap_gtc(dev, apdev):
471     """Hotspot 2.0 connection with PEAP/GTC"""
472     eap_test(dev[0], apdev[0], "25[3:6]", "PEAP", "user")
473
474 def test_ap_hs20_eap_peap_unknown(dev, apdev):
475     """Hotspot 2.0 connection with PEAP/unknown"""
476     bssid = apdev[0]['bssid']
477     params = hs20_ap_params()
478     params['nai_realm'] = "0,example.com,25[3:99]"
479     hostapd.add_ap(apdev[0]['ifname'], params)
480
481     dev[0].hs20_enable()
482     dev[0].add_cred_values(default_cred())
483     interworking_select(dev[0], None, no_match=True, freq="2412")
484
485 def test_ap_hs20_eap_ttls_chap(dev, apdev):
486     """Hotspot 2.0 connection with TTLS/CHAP"""
487     eap_test(dev[0], apdev[0], "21[2:2]", "TTLS", "chap user")
488
489 def test_ap_hs20_eap_ttls_mschap(dev, apdev):
490     """Hotspot 2.0 connection with TTLS/MSCHAP"""
491     eap_test(dev[0], apdev[0], "21[2:3]", "TTLS", "mschap user")
492
493 def test_ap_hs20_eap_ttls_eap_mschapv2(dev, apdev):
494     """Hotspot 2.0 connection with TTLS/EAP-MSCHAPv2"""
495     eap_test(dev[0], apdev[0], "21[3:26][6:7][99:99]", "TTLS", "user")
496
497 def test_ap_hs20_eap_ttls_eap_unknown(dev, apdev):
498     """Hotspot 2.0 connection with TTLS/EAP-unknown"""
499     bssid = apdev[0]['bssid']
500     params = hs20_ap_params()
501     params['nai_realm'] = "0,example.com,21[3:99]"
502     hostapd.add_ap(apdev[0]['ifname'], params)
503
504     dev[0].hs20_enable()
505     dev[0].add_cred_values(default_cred())
506     interworking_select(dev[0], None, no_match=True, freq="2412")
507
508 def test_ap_hs20_eap_ttls_eap_unsupported(dev, apdev):
509     """Hotspot 2.0 connection with TTLS/EAP-OTP(unsupported)"""
510     bssid = apdev[0]['bssid']
511     params = hs20_ap_params()
512     params['nai_realm'] = "0,example.com,21[3:5]"
513     hostapd.add_ap(apdev[0]['ifname'], params)
514
515     dev[0].hs20_enable()
516     dev[0].add_cred_values(default_cred())
517     interworking_select(dev[0], None, no_match=True, freq="2412")
518
519 def test_ap_hs20_eap_ttls_unknown(dev, apdev):
520     """Hotspot 2.0 connection with TTLS/unknown"""
521     bssid = apdev[0]['bssid']
522     params = hs20_ap_params()
523     params['nai_realm'] = "0,example.com,21[2:5]"
524     hostapd.add_ap(apdev[0]['ifname'], params)
525
526     dev[0].hs20_enable()
527     dev[0].add_cred_values(default_cred())
528     interworking_select(dev[0], None, no_match=True, freq="2412")
529
530 def test_ap_hs20_eap_fast_mschapv2(dev, apdev):
531     """Hotspot 2.0 connection with FAST/EAP-MSCHAPV2"""
532     eap_test(dev[0], apdev[0], "43[3:26]", "FAST", "user")
533
534 def test_ap_hs20_eap_fast_gtc(dev, apdev):
535     """Hotspot 2.0 connection with FAST/EAP-GTC"""
536     eap_test(dev[0], apdev[0], "43[3:6]", "FAST", "user")
537
538 def test_ap_hs20_eap_tls(dev, apdev):
539     """Hotspot 2.0 connection with EAP-TLS"""
540     bssid = apdev[0]['bssid']
541     params = hs20_ap_params()
542     params['nai_realm'] = [ "0,example.com,13[5:6]" ]
543     hostapd.add_ap(apdev[0]['ifname'], params)
544
545     dev[0].hs20_enable()
546     dev[0].add_cred_values({ 'realm': "example.com",
547                              'username': "certificate-user",
548                              'ca_cert': "auth_serv/ca.pem",
549                              'client_cert': "auth_serv/user.pem",
550                              'private_key': "auth_serv/user.key"})
551     interworking_select(dev[0], bssid, freq="2412")
552     interworking_connect(dev[0], bssid, "TLS")
553
554 def test_ap_hs20_eap_cert_unknown(dev, apdev):
555     """Hotspot 2.0 connection with certificate, but unknown EAP method"""
556     bssid = apdev[0]['bssid']
557     params = hs20_ap_params()
558     params['nai_realm'] = [ "0,example.com,99[5:6]" ]
559     hostapd.add_ap(apdev[0]['ifname'], params)
560
561     dev[0].hs20_enable()
562     dev[0].add_cred_values({ 'realm': "example.com",
563                              'username': "certificate-user",
564                              'ca_cert': "auth_serv/ca.pem",
565                              'client_cert': "auth_serv/user.pem",
566                              'private_key': "auth_serv/user.key"})
567     interworking_select(dev[0], None, no_match=True, freq="2412")
568
569 def test_ap_hs20_eap_cert_unsupported(dev, apdev):
570     """Hotspot 2.0 connection with certificate, but unsupported TTLS"""
571     bssid = apdev[0]['bssid']
572     params = hs20_ap_params()
573     params['nai_realm'] = [ "0,example.com,21[5:6]" ]
574     hostapd.add_ap(apdev[0]['ifname'], params)
575
576     dev[0].hs20_enable()
577     dev[0].add_cred_values({ 'realm': "example.com",
578                              'username': "certificate-user",
579                              'ca_cert': "auth_serv/ca.pem",
580                              'client_cert': "auth_serv/user.pem",
581                              'private_key': "auth_serv/user.key"})
582     interworking_select(dev[0], None, no_match=True, freq="2412")
583
584 def test_ap_hs20_eap_invalid_cred(dev, apdev):
585     """Hotspot 2.0 connection with invalid cred configuration"""
586     bssid = apdev[0]['bssid']
587     params = hs20_ap_params()
588     hostapd.add_ap(apdev[0]['ifname'], params)
589
590     dev[0].hs20_enable()
591     dev[0].add_cred_values({ 'realm': "example.com",
592                              'username': "certificate-user",
593                              'client_cert': "auth_serv/user.pem" })
594     interworking_select(dev[0], None, no_match=True, freq="2412")
595
596 def test_ap_hs20_nai_realms(dev, apdev):
597     """Hotspot 2.0 connection and multiple NAI realms and TTLS/PAP"""
598     bssid = apdev[0]['bssid']
599     params = hs20_ap_params()
600     params['hessid'] = bssid
601     params['nai_realm'] = [ "0,no.match.here;example.com;no.match.here.either,21[2:1][5:7]" ]
602     hostapd.add_ap(apdev[0]['ifname'], params)
603
604     dev[0].hs20_enable()
605     id = dev[0].add_cred_values({ 'realm': "example.com",
606                                   'username': "pap user",
607                                   'password': "password",
608                                   'domain': "example.com" })
609     interworking_select(dev[0], bssid, "home", freq="2412")
610     interworking_connect(dev[0], bssid, "TTLS")
611     check_sp_type(dev[0], "home")
612
613 def test_ap_hs20_roaming_consortium(dev, apdev):
614     """Hotspot 2.0 connection based on roaming consortium match"""
615     bssid = apdev[0]['bssid']
616     params = hs20_ap_params()
617     params['hessid'] = bssid
618     hostapd.add_ap(apdev[0]['ifname'], params)
619
620     dev[0].hs20_enable()
621     for consortium in [ "112233", "1020304050", "010203040506", "fedcba" ]:
622         id = dev[0].add_cred_values({ 'username': "user",
623                                       'password': "password",
624                                       'domain': "example.com",
625                                       'roaming_consortium': consortium,
626                                       'eap': "PEAP" })
627         interworking_select(dev[0], bssid, "home", freq="2412")
628         interworking_connect(dev[0], bssid, "PEAP")
629         check_sp_type(dev[0], "home")
630         dev[0].request("INTERWORKING_SELECT auto freq=2412")
631         ev = dev[0].wait_event(["INTERWORKING-ALREADY-CONNECTED"], timeout=15)
632         if ev is None:
633             raise Exception("Timeout on already-connected event")
634         dev[0].remove_cred(id)
635
636 def test_ap_hs20_username_roaming(dev, apdev):
637     """Hotspot 2.0 connection in username/password credential (roaming)"""
638     bssid = apdev[0]['bssid']
639     params = hs20_ap_params()
640     params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]",
641                             "0,roaming.example.com,21[2:4][5:7]",
642                             "0,another.example.com" ]
643     params['domain_name'] = "another.example.com"
644     params['hessid'] = bssid
645     hostapd.add_ap(apdev[0]['ifname'], params)
646
647     dev[0].hs20_enable()
648     id = dev[0].add_cred_values({ 'realm': "roaming.example.com",
649                                   'username': "hs20-test",
650                                   'password': "password",
651                                   'domain': "example.com" })
652     interworking_select(dev[0], bssid, "roaming", freq="2412")
653     interworking_connect(dev[0], bssid, "TTLS")
654     check_sp_type(dev[0], "roaming")
655
656 def test_ap_hs20_username_unknown(dev, apdev):
657     """Hotspot 2.0 connection in username/password credential (no domain in cred)"""
658     bssid = apdev[0]['bssid']
659     params = hs20_ap_params()
660     params['hessid'] = bssid
661     hostapd.add_ap(apdev[0]['ifname'], params)
662
663     dev[0].hs20_enable()
664     id = dev[0].add_cred_values({ 'realm': "example.com",
665                                   'username': "hs20-test",
666                                   'password': "password" })
667     interworking_select(dev[0], bssid, "unknown", freq="2412")
668     interworking_connect(dev[0], bssid, "TTLS")
669     check_sp_type(dev[0], "unknown")
670
671 def test_ap_hs20_username_unknown2(dev, apdev):
672     """Hotspot 2.0 connection in username/password credential (no domain advertized)"""
673     bssid = apdev[0]['bssid']
674     params = hs20_ap_params()
675     params['hessid'] = bssid
676     del params['domain_name']
677     hostapd.add_ap(apdev[0]['ifname'], params)
678
679     dev[0].hs20_enable()
680     id = dev[0].add_cred_values({ 'realm': "example.com",
681                                   'username': "hs20-test",
682                                   'password': "password",
683                                   'domain': "example.com" })
684     interworking_select(dev[0], bssid, "unknown", freq="2412")
685     interworking_connect(dev[0], bssid, "TTLS")
686     check_sp_type(dev[0], "unknown")
687
688 def test_ap_hs20_gas_while_associated(dev, apdev):
689     """Hotspot 2.0 connection with GAS query while associated"""
690     bssid = apdev[0]['bssid']
691     params = hs20_ap_params()
692     params['hessid'] = bssid
693     hostapd.add_ap(apdev[0]['ifname'], params)
694
695     dev[0].hs20_enable()
696     id = dev[0].add_cred_values({ 'realm': "example.com",
697                                   'username': "hs20-test",
698                                   'password': "password",
699                                   'domain': "example.com" })
700     interworking_select(dev[0], bssid, "home", freq="2412")
701     interworking_connect(dev[0], bssid, "TTLS")
702
703     logger.info("Verifying GAS query while associated")
704     dev[0].request("FETCH_ANQP")
705     for i in range(0, 6):
706         ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
707         if ev is None:
708             raise Exception("Operation timed out")
709
710 def test_ap_hs20_gas_while_associated_with_pmf(dev, apdev):
711     """Hotspot 2.0 connection with GAS query while associated and using PMF"""
712     bssid = apdev[0]['bssid']
713     params = hs20_ap_params()
714     params['hessid'] = bssid
715     hostapd.add_ap(apdev[0]['ifname'], params)
716
717     bssid2 = apdev[1]['bssid']
718     params = hs20_ap_params()
719     params['hessid'] = bssid2
720     params['nai_realm'] = [ "0,no-match.example.org,13[5:6],21[2:4][5:7]" ]
721     hostapd.add_ap(apdev[1]['ifname'], params)
722
723     dev[0].hs20_enable()
724     dev[0].request("SET pmf 2")
725     id = dev[0].add_cred_values({ 'realm': "example.com",
726                                   'username': "hs20-test",
727                                   'password': "password",
728                                   'domain': "example.com" })
729     interworking_select(dev[0], bssid, "home", freq="2412")
730     interworking_connect(dev[0], bssid, "TTLS")
731
732     logger.info("Verifying GAS query while associated")
733     dev[0].request("FETCH_ANQP")
734     for i in range(0, 2 * 6):
735         ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
736         if ev is None:
737             raise Exception("Operation timed out")
738
739 def test_ap_hs20_gas_frag_while_associated(dev, apdev):
740     """Hotspot 2.0 connection with fragmented GAS query while associated"""
741     bssid = apdev[0]['bssid']
742     params = hs20_ap_params()
743     params['hessid'] = bssid
744     hostapd.add_ap(apdev[0]['ifname'], params)
745     hapd = hostapd.Hostapd(apdev[0]['ifname'])
746     hapd.set("gas_frag_limit", "50")
747
748     dev[0].hs20_enable()
749     id = dev[0].add_cred_values({ 'realm': "example.com",
750                                   'username': "hs20-test",
751                                   'password': "password",
752                                   'domain': "example.com" })
753     interworking_select(dev[0], bssid, "home", freq="2412")
754     interworking_connect(dev[0], bssid, "TTLS")
755
756     logger.info("Verifying GAS query while associated")
757     dev[0].request("FETCH_ANQP")
758     for i in range(0, 6):
759         ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
760         if ev is None:
761             raise Exception("Operation timed out")
762
763 def test_ap_hs20_multiple_connects(dev, apdev):
764     """Hotspot 2.0 connection through multiple network selections"""
765     bssid = apdev[0]['bssid']
766     params = hs20_ap_params()
767     params['hessid'] = bssid
768     hostapd.add_ap(apdev[0]['ifname'], params)
769
770     dev[0].hs20_enable()
771     values = { 'realm': "example.com",
772                'username': "hs20-test",
773                'password': "password",
774                'domain': "example.com" }
775     id = dev[0].add_cred_values(values)
776
777     for i in range(0, 3):
778         logger.info("Starting Interworking network selection")
779         dev[0].request("INTERWORKING_SELECT auto freq=2412")
780         while True:
781             ev = dev[0].wait_event(["INTERWORKING-NO-MATCH",
782                                     "INTERWORKING-ALREADY-CONNECTED",
783                                     "CTRL-EVENT-CONNECTED"], timeout=15)
784             if ev is None:
785                 raise Exception("Connection timed out")
786             if "INTERWORKING-NO-MATCH" in ev:
787                 raise Exception("Matching AP not found")
788             if "CTRL-EVENT-CONNECTED" in ev:
789                 break
790             if i == 2 and "INTERWORKING-ALREADY-CONNECTED" in ev:
791                 break
792         if i == 0:
793             dev[0].request("DISCONNECT")
794         dev[0].dump_monitor()
795
796     networks = dev[0].list_networks()
797     if len(networks) > 1:
798         raise Exception("Duplicated network block detected")
799
800 def test_ap_hs20_disallow_aps(dev, apdev):
801     """Hotspot 2.0 connection and disallow_aps"""
802     bssid = apdev[0]['bssid']
803     params = hs20_ap_params()
804     params['hessid'] = bssid
805     hostapd.add_ap(apdev[0]['ifname'], params)
806
807     dev[0].hs20_enable()
808     values = { 'realm': "example.com",
809                'username': "hs20-test",
810                'password': "password",
811                'domain': "example.com" }
812     id = dev[0].add_cred_values(values)
813
814     logger.info("Verify disallow_aps bssid")
815     dev[0].request("SET disallow_aps bssid " + bssid.translate(None, ':'))
816     dev[0].request("INTERWORKING_SELECT auto")
817     ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=15)
818     if ev is None:
819         raise Exception("Network selection timed out")
820     dev[0].dump_monitor()
821
822     logger.info("Verify disallow_aps ssid")
823     dev[0].request("SET disallow_aps ssid 746573742d68733230")
824     dev[0].request("INTERWORKING_SELECT auto freq=2412")
825     ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=15)
826     if ev is None:
827         raise Exception("Network selection timed out")
828     dev[0].dump_monitor()
829
830     logger.info("Verify disallow_aps clear")
831     dev[0].request("SET disallow_aps ")
832     interworking_select(dev[0], bssid, "home", freq="2412")
833
834     dev[0].request("SET disallow_aps bssid " + bssid.translate(None, ':'))
835     ret = dev[0].request("INTERWORKING_CONNECT " + bssid)
836     if "FAIL" not in ret:
837         raise Exception("INTERWORKING_CONNECT to disallowed BSS not rejected")
838
839 def policy_test(dev, ap, values, only_one=True):
840     dev.dump_monitor()
841     if ap:
842         logger.info("Verify network selection to AP " + ap['ifname'])
843         bssid = ap['bssid']
844     else:
845         logger.info("Verify network selection")
846         bssid = None
847     dev.hs20_enable()
848     id = dev.add_cred_values(values)
849     dev.request("INTERWORKING_SELECT auto freq=2412")
850     events = []
851     while True:
852         ev = dev.wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH",
853                              "INTERWORKING-BLACKLISTED",
854                              "INTERWORKING-SELECTED"], timeout=15)
855         if ev is None:
856             raise Exception("Network selection timed out")
857         events.append(ev)
858         if "INTERWORKING-NO-MATCH" in ev:
859             raise Exception("Matching AP not found")
860         if bssid and only_one and "INTERWORKING-AP" in ev and bssid not in ev:
861             raise Exception("Unexpected AP claimed acceptable")
862         if "INTERWORKING-SELECTED" in ev:
863             if bssid and bssid not in ev:
864                 raise Exception("Selected incorrect BSS")
865             break
866
867     ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
868     if ev is None:
869         raise Exception("Connection timed out")
870     if bssid and bssid not in ev:
871         raise Exception("Connected to incorrect BSS")
872
873     conn_bssid = dev.get_status_field("bssid")
874     if bssid and conn_bssid != bssid:
875         raise Exception("bssid information points to incorrect BSS")
876
877     dev.remove_cred(id)
878     dev.dump_monitor()
879     return events
880
881 def default_cred(domain=None):
882     cred = { 'realm': "example.com",
883              'username': "hs20-test",
884              'password': "password" }
885     if domain:
886         cred['domain'] = domain
887     return cred
888
889 def test_ap_hs20_prefer_home(dev, apdev):
890     """Hotspot 2.0 required roaming consortium"""
891     params = hs20_ap_params()
892     params['domain_name'] = "example.org"
893     hostapd.add_ap(apdev[0]['ifname'], params)
894
895     params = hs20_ap_params()
896     params['ssid'] = "test-hs20-other"
897     params['domain_name'] = "example.com"
898     hostapd.add_ap(apdev[1]['ifname'], params)
899
900     values = default_cred()
901     values['domain'] = "example.com"
902     policy_test(dev[0], apdev[1], values, only_one=False)
903     values['domain'] = "example.org"
904     policy_test(dev[0], apdev[0], values, only_one=False)
905
906 def test_ap_hs20_req_roaming_consortium(dev, apdev):
907     """Hotspot 2.0 required roaming consortium"""
908     params = hs20_ap_params()
909     hostapd.add_ap(apdev[0]['ifname'], params)
910
911     params = hs20_ap_params()
912     params['ssid'] = "test-hs20-other"
913     params['roaming_consortium'] = [ "223344" ]
914     hostapd.add_ap(apdev[1]['ifname'], params)
915
916     values = default_cred()
917     values['required_roaming_consortium'] = "223344"
918     policy_test(dev[0], apdev[1], values)
919     values['required_roaming_consortium'] = "112233"
920     policy_test(dev[0], apdev[0], values)
921
922     id = dev[0].add_cred()
923     dev[0].set_cred(id, "required_roaming_consortium", "112233")
924     dev[0].set_cred(id, "required_roaming_consortium", "112233445566778899aabbccddeeff")
925
926     for val in [ "", "1", "11", "1122", "1122334", "112233445566778899aabbccddeeff00" ]:
927         if "FAIL" not in dev[0].request('SET_CRED {} required_roaming_consortium {}'.format(id, val)):
928             raise Exception("Invalid roaming consortium value accepted: " + val)
929
930 def test_ap_hs20_excluded_ssid(dev, apdev):
931     """Hotspot 2.0 exclusion based on SSID"""
932     params = hs20_ap_params()
933     params['roaming_consortium'] = [ "223344" ]
934     params['anqp_3gpp_cell_net'] = "555,444"
935     hostapd.add_ap(apdev[0]['ifname'], params)
936
937     params = hs20_ap_params()
938     params['ssid'] = "test-hs20-other"
939     params['roaming_consortium'] = [ "223344" ]
940     params['anqp_3gpp_cell_net'] = "555,444"
941     hostapd.add_ap(apdev[1]['ifname'], params)
942
943     values = default_cred()
944     values['excluded_ssid'] = "test-hs20"
945     events = policy_test(dev[0], apdev[1], values)
946     ev = [e for e in events if "INTERWORKING-BLACKLISTED " + apdev[0]['bssid'] in e]
947     if len(ev) != 1:
948         raise Exception("Excluded network not reported")
949     values['excluded_ssid'] = "test-hs20-other"
950     events = policy_test(dev[0], apdev[0], values)
951     ev = [e for e in events if "INTERWORKING-BLACKLISTED " + apdev[1]['bssid'] in e]
952     if len(ev) != 1:
953         raise Exception("Excluded network not reported")
954
955     values = default_cred()
956     values['roaming_consortium'] = "223344"
957     values['eap'] = "TTLS"
958     values['phase2'] = "auth=MSCHAPV2"
959     values['excluded_ssid'] = "test-hs20"
960     events = policy_test(dev[0], apdev[1], values)
961     ev = [e for e in events if "INTERWORKING-BLACKLISTED " + apdev[0]['bssid'] in e]
962     if len(ev) != 1:
963         raise Exception("Excluded network not reported")
964
965     values = { 'imsi': "555444-333222111", 'eap': "SIM",
966                'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123",
967                'excluded_ssid': "test-hs20" }
968     events = policy_test(dev[0], apdev[1], values)
969     ev = [e for e in events if "INTERWORKING-BLACKLISTED " + apdev[0]['bssid'] in e]
970     if len(ev) != 1:
971         raise Exception("Excluded network not reported")
972
973 def test_ap_hs20_roam_to_higher_prio(dev, apdev):
974     """Hotspot 2.0 and roaming from current to higher priority network"""
975     bssid = apdev[0]['bssid']
976     params = hs20_ap_params(ssid="test-hs20-visited")
977     params['domain_name'] = "visited.example.org"
978     hostapd.add_ap(apdev[0]['ifname'], params)
979
980     dev[0].hs20_enable()
981     id = dev[0].add_cred_values({ 'realm': "example.com",
982                                   'username': "hs20-test",
983                                   'password': "password",
984                                   'domain': "example.com" })
985     logger.info("Connect to the only network option")
986     interworking_select(dev[0], bssid, "roaming", freq="2412")
987     dev[0].dump_monitor()
988     interworking_connect(dev[0], bssid, "TTLS")
989
990     logger.info("Start another AP (home operator) and reconnect")
991     bssid2 = apdev[1]['bssid']
992     params = hs20_ap_params(ssid="test-hs20-home")
993     params['domain_name'] = "example.com"
994     hostapd.add_ap(apdev[1]['ifname'], params)
995
996     dev[0].request("INTERWORKING_SELECT auto freq=2412")
997     ev = dev[0].wait_event(["INTERWORKING-NO-MATCH",
998                             "INTERWORKING-ALREADY-CONNECTED",
999                             "CTRL-EVENT-CONNECTED"], timeout=15)
1000     if ev is None:
1001         raise Exception("Connection timed out")
1002     if "INTERWORKING-NO-MATCH" in ev:
1003         raise Exception("Matching AP not found")
1004     if "INTERWORKING-ALREADY-CONNECTED" in ev:
1005         raise Exception("Unexpected AP selected")
1006     if bssid2 not in ev:
1007         raise Exception("Unexpected BSSID after reconnection")
1008
1009 def test_ap_hs20_domain_suffix_match(dev, apdev):
1010     """Hotspot 2.0 and domain_suffix_match"""
1011     bssid = apdev[0]['bssid']
1012     params = hs20_ap_params()
1013     hostapd.add_ap(apdev[0]['ifname'], params)
1014
1015     dev[0].hs20_enable()
1016     id = dev[0].add_cred_values({ 'realm': "example.com",
1017                                   'username': "hs20-test",
1018                                   'password': "password",
1019                                   'domain': "example.com",
1020                                   'domain_suffix_match': "w1.fi" })
1021     interworking_select(dev[0], bssid, "home", freq="2412")
1022     dev[0].dump_monitor()
1023     interworking_connect(dev[0], bssid, "TTLS")
1024     dev[0].request("REMOVE_NETWORK all")
1025     dev[0].dump_monitor()
1026
1027     dev[0].set_cred_quoted(id, "domain_suffix_match", "no-match.example.com")
1028     interworking_select(dev[0], bssid, "home", freq="2412")
1029     dev[0].dump_monitor()
1030     dev[0].request("INTERWORKING_CONNECT " + bssid)
1031     ev = dev[0].wait_event(["CTRL-EVENT-EAP-TLS-CERT-ERROR"])
1032     if ev is None:
1033         raise Exception("TLS certificate error not reported")
1034     if "Domain suffix mismatch" not in ev:
1035         raise Exception("Domain suffix mismatch not reported")
1036
1037 def test_ap_hs20_roaming_partner_preference(dev, apdev):
1038     """Hotspot 2.0 and roaming partner preference"""
1039     params = hs20_ap_params()
1040     params['domain_name'] = "roaming.example.org"
1041     hostapd.add_ap(apdev[0]['ifname'], params)
1042
1043     params = hs20_ap_params()
1044     params['ssid'] = "test-hs20-other"
1045     params['domain_name'] = "roaming.example.net"
1046     hostapd.add_ap(apdev[1]['ifname'], params)
1047
1048     logger.info("Verify default vs. specified preference")
1049     values = default_cred()
1050     values['roaming_partner'] = "roaming.example.net,1,127,*"
1051     policy_test(dev[0], apdev[1], values, only_one=False)
1052     values['roaming_partner'] = "roaming.example.net,1,129,*"
1053     policy_test(dev[0], apdev[0], values, only_one=False)
1054
1055     logger.info("Verify partial FQDN match")
1056     values['roaming_partner'] = "example.net,0,0,*"
1057     policy_test(dev[0], apdev[1], values, only_one=False)
1058     values['roaming_partner'] = "example.net,0,255,*"
1059     policy_test(dev[0], apdev[0], values, only_one=False)
1060
1061 def test_ap_hs20_max_bss_load(dev, apdev):
1062     """Hotspot 2.0 and maximum BSS load"""
1063     params = hs20_ap_params()
1064     params['bss_load_test'] = "12:200:20000"
1065     hostapd.add_ap(apdev[0]['ifname'], params)
1066
1067     params = hs20_ap_params()
1068     params['ssid'] = "test-hs20-other"
1069     params['bss_load_test'] = "5:20:10000"
1070     hostapd.add_ap(apdev[1]['ifname'], params)
1071
1072     logger.info("Verify maximum BSS load constraint")
1073     values = default_cred()
1074     values['domain'] = "example.com"
1075     values['max_bss_load'] = "100"
1076     events = policy_test(dev[0], apdev[1], values, only_one=False)
1077
1078     ev = [e for e in events if "INTERWORKING-AP " + apdev[0]['bssid'] in e]
1079     if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
1080         raise Exception("Maximum BSS Load case not noticed")
1081     ev = [e for e in events if "INTERWORKING-AP " + apdev[1]['bssid'] in e]
1082     if len(ev) != 1 or "over_max_bss_load=1" in ev[0]:
1083         raise Exception("Maximum BSS Load case reported incorrectly")
1084
1085     logger.info("Verify maximum BSS load does not prevent connection")
1086     values['max_bss_load'] = "1"
1087     events = policy_test(dev[0], None, values)
1088
1089     ev = [e for e in events if "INTERWORKING-AP " + apdev[0]['bssid'] in e]
1090     if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
1091         raise Exception("Maximum BSS Load case not noticed")
1092     ev = [e for e in events if "INTERWORKING-AP " + apdev[1]['bssid'] in e]
1093     if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
1094         raise Exception("Maximum BSS Load case not noticed")
1095
1096 def test_ap_hs20_max_bss_load2(dev, apdev):
1097     """Hotspot 2.0 and maximum BSS load with one AP not advertising"""
1098     params = hs20_ap_params()
1099     params['bss_load_test'] = "12:200:20000"
1100     hostapd.add_ap(apdev[0]['ifname'], params)
1101
1102     params = hs20_ap_params()
1103     params['ssid'] = "test-hs20-other"
1104     hostapd.add_ap(apdev[1]['ifname'], params)
1105
1106     logger.info("Verify maximum BSS load constraint with AP advertisement")
1107     values = default_cred()
1108     values['domain'] = "example.com"
1109     values['max_bss_load'] = "100"
1110     events = policy_test(dev[0], apdev[1], values, only_one=False)
1111
1112     ev = [e for e in events if "INTERWORKING-AP " + apdev[0]['bssid'] in e]
1113     if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
1114         raise Exception("Maximum BSS Load case not noticed")
1115     ev = [e for e in events if "INTERWORKING-AP " + apdev[1]['bssid'] in e]
1116     if len(ev) != 1 or "over_max_bss_load=1" in ev[0]:
1117         raise Exception("Maximum BSS Load case reported incorrectly")
1118
1119 def test_ap_hs20_multi_cred_sp_prio(dev, apdev):
1120     """Hotspot 2.0 multi-cred sp_priority"""
1121     if not hlr_auc_gw_available():
1122         return "skip"
1123     bssid = apdev[0]['bssid']
1124     params = hs20_ap_params()
1125     params['hessid'] = bssid
1126     del params['domain_name']
1127     params['anqp_3gpp_cell_net'] = "232,01"
1128     hostapd.add_ap(apdev[0]['ifname'], params)
1129
1130     dev[0].hs20_enable()
1131     dev[0].request("SET external_sim 1")
1132     id1 = dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM",
1133                                    'provisioning_sp': "example.com",
1134                                    'sp_priority' :"1" })
1135     id2 = dev[0].add_cred_values({ 'realm': "example.com",
1136                                    'username': "hs20-test",
1137                                    'password': "password",
1138                                    'domain': "example.com",
1139                                    'provisioning_sp': "example.com",
1140                                    'sp_priority': "2" })
1141     dev[0].dump_monitor()
1142     dev[0].request("INTERWORKING_SELECT auto freq=2412")
1143     interworking_ext_sim_auth(dev[0], "SIM")
1144     check_sp_type(dev[0], "unknown")
1145     dev[0].request("REMOVE_NETWORK all")
1146
1147     dev[0].set_cred(id1, "sp_priority", "2")
1148     dev[0].set_cred(id2, "sp_priority", "1")
1149     dev[0].dump_monitor()
1150     dev[0].request("INTERWORKING_SELECT auto freq=2412")
1151     interworking_auth(dev[0], "TTLS")
1152     check_sp_type(dev[0], "unknown")
1153
1154 def test_ap_hs20_multi_cred_sp_prio2(dev, apdev):
1155     """Hotspot 2.0 multi-cred sp_priority with two BSSes"""
1156     if not hlr_auc_gw_available():
1157         return "skip"
1158     bssid = apdev[0]['bssid']
1159     params = hs20_ap_params()
1160     params['hessid'] = bssid
1161     del params['nai_realm']
1162     del params['domain_name']
1163     params['anqp_3gpp_cell_net'] = "232,01"
1164     hostapd.add_ap(apdev[0]['ifname'], params)
1165
1166     bssid2 = apdev[1]['bssid']
1167     params = hs20_ap_params()
1168     params['ssid'] = "test-hs20-other"
1169     params['hessid'] = bssid2
1170     del params['domain_name']
1171     del params['anqp_3gpp_cell_net']
1172     hostapd.add_ap(apdev[1]['ifname'], params)
1173
1174     dev[0].hs20_enable()
1175     dev[0].request("SET external_sim 1")
1176     id1 = dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM",
1177                                    'provisioning_sp': "example.com",
1178                                    'sp_priority': "1" })
1179     id2 = dev[0].add_cred_values({ 'realm': "example.com",
1180                                    'username': "hs20-test",
1181                                    'password': "password",
1182                                    'domain': "example.com",
1183                                    'provisioning_sp': "example.com",
1184                                    'sp_priority': "2" })
1185     dev[0].dump_monitor()
1186     dev[0].request("INTERWORKING_SELECT auto freq=2412")
1187     interworking_ext_sim_auth(dev[0], "SIM")
1188     check_sp_type(dev[0], "unknown")
1189     conn_bssid = dev[0].get_status_field("bssid")
1190     if conn_bssid != bssid:
1191         raise Exception("Connected to incorrect BSS")
1192     dev[0].request("REMOVE_NETWORK all")
1193
1194     dev[0].set_cred(id1, "sp_priority", "2")
1195     dev[0].set_cred(id2, "sp_priority", "1")
1196     dev[0].dump_monitor()
1197     dev[0].request("INTERWORKING_SELECT auto freq=2412")
1198     interworking_auth(dev[0], "TTLS")
1199     check_sp_type(dev[0], "unknown")
1200     conn_bssid = dev[0].get_status_field("bssid")
1201     if conn_bssid != bssid2:
1202         raise Exception("Connected to incorrect BSS")
1203
1204 def check_conn_capab_selection(dev, type, missing):
1205     dev.request("INTERWORKING_SELECT freq=2412")
1206     ev = dev.wait_event(["INTERWORKING-AP"])
1207     if ev is None:
1208         raise Exception("Network selection timed out");
1209     if "type=" + type not in ev:
1210         raise Exception("Unexpected network type")
1211     if missing and "conn_capab_missing=1" not in ev:
1212         raise Exception("conn_capab_missing not reported")
1213     if not missing and "conn_capab_missing=1" in ev:
1214         raise Exception("conn_capab_missing reported unexpectedly")
1215
1216 def conn_capab_cred(domain=None, req_conn_capab=None):
1217     cred = default_cred(domain=domain)
1218     if req_conn_capab:
1219         cred['req_conn_capab'] = req_conn_capab
1220     return cred
1221
1222 def test_ap_hs20_req_conn_capab(dev, apdev):
1223     """Hotspot 2.0 network selection with req_conn_capab"""
1224     bssid = apdev[0]['bssid']
1225     params = hs20_ap_params()
1226     hostapd.add_ap(apdev[0]['ifname'], params)
1227
1228     dev[0].hs20_enable()
1229     logger.info("Not used in home network")
1230     values = conn_capab_cred(domain="example.com", req_conn_capab="6:1234")
1231     id = dev[0].add_cred_values(values)
1232     check_conn_capab_selection(dev[0], "home", False)
1233
1234     logger.info("Used in roaming network")
1235     dev[0].remove_cred(id)
1236     values = conn_capab_cred(domain="example.org", req_conn_capab="6:1234")
1237     id = dev[0].add_cred_values(values)
1238     check_conn_capab_selection(dev[0], "roaming", True)
1239
1240     logger.info("Verify that req_conn_capab does not prevent connection if no other network is available")
1241     check_auto_select(dev[0], bssid)
1242
1243     logger.info("Additional req_conn_capab checks")
1244
1245     dev[0].remove_cred(id)
1246     values = conn_capab_cred(domain="example.org", req_conn_capab="1:0")
1247     id = dev[0].add_cred_values(values)
1248     check_conn_capab_selection(dev[0], "roaming", True)
1249
1250     dev[0].remove_cred(id)
1251     values = conn_capab_cred(domain="example.org", req_conn_capab="17:5060")
1252     id = dev[0].add_cred_values(values)
1253     check_conn_capab_selection(dev[0], "roaming", True)
1254
1255     bssid2 = apdev[1]['bssid']
1256     params = hs20_ap_params(ssid="test-hs20b")
1257     params['hs20_conn_capab'] = [ "1:0:2", "6:22:1", "17:5060:0", "50:0:1" ]
1258     hostapd.add_ap(apdev[1]['ifname'], params)
1259
1260     dev[0].remove_cred(id)
1261     values = conn_capab_cred(domain="example.org", req_conn_capab="50")
1262     id = dev[0].add_cred_values(values)
1263     dev[0].set_cred(id, "req_conn_capab", "6:22")
1264     dev[0].request("INTERWORKING_SELECT freq=2412")
1265     for i in range(0, 2):
1266         ev = dev[0].wait_event(["INTERWORKING-AP"])
1267         if ev is None:
1268             raise Exception("Network selection timed out");
1269         if bssid in ev and "conn_capab_missing=1" not in ev:
1270             raise Exception("Missing protocol connection capability not reported")
1271         if bssid2 in ev and "conn_capab_missing=1" in ev:
1272             raise Exception("Protocol connection capability not reported correctly")
1273
1274 def test_ap_hs20_req_conn_capab_and_roaming_partner_preference(dev, apdev):
1275     """Hotspot 2.0 and req_conn_capab with roaming partner preference"""
1276     bssid = apdev[0]['bssid']
1277     params = hs20_ap_params()
1278     params['domain_name'] = "roaming.example.org"
1279     params['hs20_conn_capab'] = [ "1:0:2", "6:22:1", "17:5060:0", "50:0:1" ]
1280     hostapd.add_ap(apdev[0]['ifname'], params)
1281
1282     bssid2 = apdev[1]['bssid']
1283     params = hs20_ap_params(ssid="test-hs20-b")
1284     params['domain_name'] = "roaming.example.net"
1285     hostapd.add_ap(apdev[1]['ifname'], params)
1286
1287     values = default_cred()
1288     values['roaming_partner'] = "roaming.example.net,1,127,*"
1289     id = dev[0].add_cred_values(values)
1290     check_auto_select(dev[0], bssid2)
1291
1292     dev[0].set_cred(id, "req_conn_capab", "50")
1293     check_auto_select(dev[0], bssid)
1294
1295     dev[0].remove_cred(id)
1296     id = dev[0].add_cred_values(values)
1297     dev[0].set_cred(id, "req_conn_capab", "51")
1298     check_auto_select(dev[0], bssid2)
1299
1300 def check_bandwidth_selection(dev, type, below):
1301     dev.request("INTERWORKING_SELECT freq=2412")
1302     ev = dev.wait_event(["INTERWORKING-AP"])
1303     if ev is None:
1304         raise Exception("Network selection timed out");
1305     if "type=" + type not in ev:
1306         raise Exception("Unexpected network type")
1307     if below and "below_min_backhaul=1" not in ev:
1308         raise Exception("below_min_backhaul not reported")
1309     if not below and "below_min_backhaul=1" in ev:
1310         raise Exception("below_min_backhaul reported unexpectedly")
1311
1312 def bw_cred(domain=None, dl_home=None, ul_home=None, dl_roaming=None, ul_roaming=None):
1313     cred = default_cred(domain=domain)
1314     if dl_home:
1315         cred['min_dl_bandwidth_home'] = str(dl_home)
1316     if ul_home:
1317         cred['min_ul_bandwidth_home'] = str(ul_home)
1318     if dl_roaming:
1319         cred['min_dl_bandwidth_roaming'] = str(dl_roaming)
1320     if ul_roaming:
1321         cred['min_ul_bandwidth_roaming'] = str(ul_roaming)
1322     return cred
1323
1324 def test_ap_hs20_min_bandwidth_home(dev, apdev):
1325     """Hotspot 2.0 network selection with min bandwidth (home)"""
1326     bssid = apdev[0]['bssid']
1327     params = hs20_ap_params()
1328     hostapd.add_ap(apdev[0]['ifname'], params)
1329
1330     dev[0].hs20_enable()
1331     values = bw_cred(domain="example.com", dl_home=5490, ul_home=58)
1332     id = dev[0].add_cred_values(values)
1333     check_bandwidth_selection(dev[0], "home", False)
1334     dev[0].remove_cred(id)
1335
1336     values = bw_cred(domain="example.com", dl_home=5491, ul_home=58)
1337     id = dev[0].add_cred_values(values)
1338     check_bandwidth_selection(dev[0], "home", True)
1339     dev[0].remove_cred(id)
1340
1341     values = bw_cred(domain="example.com", dl_home=5490, ul_home=59)
1342     id = dev[0].add_cred_values(values)
1343     check_bandwidth_selection(dev[0], "home", True)
1344     dev[0].remove_cred(id)
1345
1346     values = bw_cred(domain="example.com", dl_home=5491, ul_home=59)
1347     id = dev[0].add_cred_values(values)
1348     check_bandwidth_selection(dev[0], "home", True)
1349     check_auto_select(dev[0], bssid)
1350
1351     bssid2 = apdev[1]['bssid']
1352     params = hs20_ap_params(ssid="test-hs20-b")
1353     params['hs20_wan_metrics'] = "01:8000:1000:1:1:3000"
1354     hostapd.add_ap(apdev[1]['ifname'], params)
1355
1356     check_auto_select(dev[0], bssid2)
1357
1358 def test_ap_hs20_min_bandwidth_roaming(dev, apdev):
1359     """Hotspot 2.0 network selection with min bandwidth (roaming)"""
1360     bssid = apdev[0]['bssid']
1361     params = hs20_ap_params()
1362     hostapd.add_ap(apdev[0]['ifname'], params)
1363
1364     dev[0].hs20_enable()
1365     values = bw_cred(domain="example.org", dl_roaming=5490, ul_roaming=58)
1366     id = dev[0].add_cred_values(values)
1367     check_bandwidth_selection(dev[0], "roaming", False)
1368     dev[0].remove_cred(id)
1369
1370     values = bw_cred(domain="example.org", dl_roaming=5491, ul_roaming=58)
1371     id = dev[0].add_cred_values(values)
1372     check_bandwidth_selection(dev[0], "roaming", True)
1373     dev[0].remove_cred(id)
1374
1375     values = bw_cred(domain="example.org", dl_roaming=5490, ul_roaming=59)
1376     id = dev[0].add_cred_values(values)
1377     check_bandwidth_selection(dev[0], "roaming", True)
1378     dev[0].remove_cred(id)
1379
1380     values = bw_cred(domain="example.org", dl_roaming=5491, ul_roaming=59)
1381     id = dev[0].add_cred_values(values)
1382     check_bandwidth_selection(dev[0], "roaming", True)
1383     check_auto_select(dev[0], bssid)
1384
1385     bssid2 = apdev[1]['bssid']
1386     params = hs20_ap_params(ssid="test-hs20-b")
1387     params['hs20_wan_metrics'] = "01:8000:1000:1:1:3000"
1388     hostapd.add_ap(apdev[1]['ifname'], params)
1389
1390     check_auto_select(dev[0], bssid2)
1391
1392 def test_ap_hs20_min_bandwidth_and_roaming_partner_preference(dev, apdev):
1393     """Hotspot 2.0 and minimum bandwidth with roaming partner preference"""
1394     bssid = apdev[0]['bssid']
1395     params = hs20_ap_params()
1396     params['domain_name'] = "roaming.example.org"
1397     params['hs20_wan_metrics'] = "01:8000:1000:1:1:3000"
1398     hostapd.add_ap(apdev[0]['ifname'], params)
1399
1400     bssid2 = apdev[1]['bssid']
1401     params = hs20_ap_params(ssid="test-hs20-b")
1402     params['domain_name'] = "roaming.example.net"
1403     hostapd.add_ap(apdev[1]['ifname'], params)
1404
1405     values = default_cred()
1406     values['roaming_partner'] = "roaming.example.net,1,127,*"
1407     id = dev[0].add_cred_values(values)
1408     check_auto_select(dev[0], bssid2)
1409
1410     dev[0].set_cred(id, "min_dl_bandwidth_roaming", "6000")
1411     check_auto_select(dev[0], bssid)
1412
1413     dev[0].set_cred(id, "min_dl_bandwidth_roaming", "10000")
1414     check_auto_select(dev[0], bssid2)
1415
1416 def test_ap_hs20_min_bandwidth_no_wan_metrics(dev, apdev):
1417     """Hotspot 2.0 network selection with min bandwidth but no WAN Metrics"""
1418     bssid = apdev[0]['bssid']
1419     params = hs20_ap_params()
1420     del params['hs20_wan_metrics']
1421     hostapd.add_ap(apdev[0]['ifname'], params)
1422
1423     dev[0].hs20_enable()
1424     values = bw_cred(domain="example.com", dl_home=10000, ul_home=10000,
1425                      dl_roaming=10000, ul_roaming=10000)
1426     dev[0].add_cred_values(values)
1427     check_bandwidth_selection(dev[0], "home", False)
1428
1429 def test_ap_hs20_deauth_req_ess(dev, apdev):
1430     """Hotspot 2.0 connection and deauthentication request for ESS"""
1431     dev[0].request("SET pmf 2")
1432     eap_test(dev[0], apdev[0], "21[3:26]", "TTLS", "user")
1433     dev[0].dump_monitor()
1434     addr = dev[0].p2p_interface_addr()
1435     hapd = hostapd.Hostapd(apdev[0]['ifname'])
1436     hapd.request("HS20_DEAUTH_REQ " + addr + " 1 120 http://example.com/")
1437     ev = dev[0].wait_event(["HS20-DEAUTH-IMMINENT-NOTICE"])
1438     if ev is None:
1439         raise Exception("Timeout on deauth imminent notice")
1440     if "1 120 http://example.com/" not in ev:
1441         raise Exception("Unexpected deauth imminent notice: " + ev)
1442     hapd.request("DEAUTHENTICATE " + addr)
1443     ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"])
1444     if ev is None:
1445         raise Exception("Timeout on disconnection")
1446     if "[TEMP-DISABLED]" not in dev[0].list_networks()[0]['flags']:
1447         raise Exception("Network not marked temporarily disabled")
1448     ev = dev[0].wait_event(["SME: Trying to authenticate",
1449                             "Trying to associate",
1450                             "CTRL-EVENT-CONNECTED"], timeout=5)
1451     if ev is not None:
1452         raise Exception("Unexpected connection attempt")
1453
1454 def test_ap_hs20_deauth_req_bss(dev, apdev):
1455     """Hotspot 2.0 connection and deauthentication request for BSS"""
1456     dev[0].request("SET pmf 2")
1457     eap_test(dev[0], apdev[0], "21[3:26]", "TTLS", "user")
1458     dev[0].dump_monitor()
1459     addr = dev[0].p2p_interface_addr()
1460     hapd = hostapd.Hostapd(apdev[0]['ifname'])
1461     hapd.request("HS20_DEAUTH_REQ " + addr + " 0 120 http://example.com/")
1462     ev = dev[0].wait_event(["HS20-DEAUTH-IMMINENT-NOTICE"])
1463     if ev is None:
1464         raise Exception("Timeout on deauth imminent notice")
1465     if "0 120 http://example.com/" not in ev:
1466         raise Exception("Unexpected deauth imminent notice: " + ev)
1467     hapd.request("DEAUTHENTICATE " + addr + " reason=4")
1468     ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"])
1469     if ev is None:
1470         raise Exception("Timeout on disconnection")
1471     if "reason=4" not in ev:
1472         raise Exception("Unexpected disconnection reason")
1473     if "[TEMP-DISABLED]" not in dev[0].list_networks()[0]['flags']:
1474         raise Exception("Network not marked temporarily disabled")
1475     ev = dev[0].wait_event(["SME: Trying to authenticate",
1476                             "Trying to associate",
1477                             "CTRL-EVENT-CONNECTED"], timeout=5)
1478     if ev is not None:
1479         raise Exception("Unexpected connection attempt")
1480
1481 def test_ap_hs20_deauth_req_from_radius(dev, apdev):
1482     """Hotspot 2.0 connection and deauthentication request from RADIUS"""
1483     bssid = apdev[0]['bssid']
1484     params = hs20_ap_params()
1485     params['nai_realm'] = [ "0,example.com,21[2:4]" ]
1486     params['hs20_deauth_req_timeout'] = "2"
1487     hostapd.add_ap(apdev[0]['ifname'], params)
1488
1489     dev[0].request("SET pmf 2")
1490     dev[0].hs20_enable()
1491     dev[0].add_cred_values({ 'realm': "example.com",
1492                              'username': "hs20-deauth-test",
1493                              'password': "password" })
1494     interworking_select(dev[0], bssid, freq="2412")
1495     interworking_connect(dev[0], bssid, "TTLS")
1496     ev = dev[0].wait_event(["HS20-DEAUTH-IMMINENT-NOTICE"], timeout=5)
1497     if ev is None:
1498         raise Exception("Timeout on deauth imminent notice")
1499     if " 1 100" not in ev:
1500         raise Exception("Unexpected deauth imminent contents")
1501     ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=3)
1502     if ev is None:
1503         raise Exception("Timeout on disconnection")
1504
1505 def test_ap_hs20_remediation_required(dev, apdev):
1506     """Hotspot 2.0 connection and remediation required from RADIUS"""
1507     bssid = apdev[0]['bssid']
1508     params = hs20_ap_params()
1509     params['nai_realm'] = [ "0,example.com,21[2:4]" ]
1510     hostapd.add_ap(apdev[0]['ifname'], params)
1511
1512     dev[0].request("SET pmf 1")
1513     dev[0].hs20_enable()
1514     dev[0].add_cred_values({ 'realm': "example.com",
1515                              'username': "hs20-subrem-test",
1516                              'password': "password" })
1517     interworking_select(dev[0], bssid, freq="2412")
1518     interworking_connect(dev[0], bssid, "TTLS")
1519     ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=5)
1520     if ev is None:
1521         raise Exception("Timeout on subscription remediation notice")
1522     if " 1 https://example.com/" not in ev:
1523         raise Exception("Unexpected subscription remediation event contents")
1524
1525 def test_ap_hs20_remediation_required_ctrl(dev, apdev):
1526     """Hotspot 2.0 connection and subrem from ctrl_iface"""
1527     bssid = apdev[0]['bssid']
1528     addr = dev[0].p2p_dev_addr()
1529     params = hs20_ap_params()
1530     params['nai_realm'] = [ "0,example.com,21[2:4]" ]
1531     hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1532
1533     dev[0].request("SET pmf 1")
1534     dev[0].hs20_enable()
1535     dev[0].add_cred_values(default_cred())
1536     interworking_select(dev[0], bssid, freq="2412")
1537     interworking_connect(dev[0], bssid, "TTLS")
1538
1539     hapd.request("HS20_WNM_NOTIF " + addr + " https://example.com/")
1540     ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=5)
1541     if ev is None:
1542         raise Exception("Timeout on subscription remediation notice")
1543     if " 1 https://example.com/" not in ev:
1544         raise Exception("Unexpected subscription remediation event contents")
1545
1546     hapd.request("HS20_WNM_NOTIF " + addr)
1547     ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=5)
1548     if ev is None:
1549         raise Exception("Timeout on subscription remediation notice")
1550     if not ev.endswith("HS20-SUBSCRIPTION-REMEDIATION "):
1551         raise Exception("Unexpected subscription remediation event contents: " + ev)
1552
1553     if "FAIL" not in hapd.request("HS20_WNM_NOTIF "):
1554         raise Exception("Unexpected HS20_WNM_NOTIF success")
1555     if "FAIL" not in hapd.request("HS20_WNM_NOTIF foo"):
1556         raise Exception("Unexpected HS20_WNM_NOTIF success")
1557     if "FAIL" not in hapd.request("HS20_WNM_NOTIF " + addr + " https://12345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678927.very.long.example.com/"):
1558         raise Exception("Unexpected HS20_WNM_NOTIF success")
1559
1560 def test_ap_hs20_session_info(dev, apdev):
1561     """Hotspot 2.0 connection and session information from RADIUS"""
1562     bssid = apdev[0]['bssid']
1563     params = hs20_ap_params()
1564     params['nai_realm'] = [ "0,example.com,21[2:4]" ]
1565     hostapd.add_ap(apdev[0]['ifname'], params)
1566
1567     dev[0].request("SET pmf 1")
1568     dev[0].hs20_enable()
1569     dev[0].add_cred_values({ 'realm': "example.com",
1570                              'username': "hs20-session-info-test",
1571                              'password': "password" })
1572     interworking_select(dev[0], bssid, freq="2412")
1573     interworking_connect(dev[0], bssid, "TTLS")
1574     ev = dev[0].wait_event(["ESS-DISASSOC-IMMINENT"], timeout=10)
1575     if ev is None:
1576         raise Exception("Timeout on ESS disassociation imminent notice")
1577     if " 1 59904 https://example.com/" not in ev:
1578         raise Exception("Unexpected ESS disassociation imminent event contents")
1579     ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"])
1580     if ev is None:
1581         raise Exception("Scan not started")
1582     ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
1583     if ev is None:
1584         raise Exception("Scan not completed")
1585
1586 def test_ap_hs20_osen(dev, apdev):
1587     """Hotspot 2.0 OSEN connection"""
1588     params = { 'ssid': "osen",
1589                'osen': "1",
1590                'auth_server_addr': "127.0.0.1",
1591                'auth_server_port': "1812",
1592                'auth_server_shared_secret': "radius" }
1593     hostapd.add_ap(apdev[0]['ifname'], params)
1594
1595     dev[0].connect("osen", proto="OSEN", key_mgmt="OSEN", pairwise="CCMP",
1596                    group="GTK_NOT_USED",
1597                    eap="WFA-UNAUTH-TLS", identity="osen@example.com",
1598                    ca_cert="auth_serv/ca.pem",
1599                    scan_freq="2412")
1600
1601 def test_ap_hs20_network_preference(dev, apdev):
1602     """Hotspot 2.0 network selection with preferred home network"""
1603     bssid = apdev[0]['bssid']
1604     params = hs20_ap_params()
1605     hostapd.add_ap(apdev[0]['ifname'], params)
1606
1607     dev[0].hs20_enable()
1608     values = { 'realm': "example.com",
1609                'username': "hs20-test",
1610                'password': "password",
1611                'domain': "example.com" }
1612     dev[0].add_cred_values(values)
1613
1614     id = dev[0].add_network()
1615     dev[0].set_network_quoted(id, "ssid", "home")
1616     dev[0].set_network_quoted(id, "psk", "12345678")
1617     dev[0].set_network(id, "priority", "1")
1618     dev[0].request("ENABLE_NETWORK %s no-connect" % id)
1619
1620     dev[0].request("INTERWORKING_SELECT auto freq=2412")
1621     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
1622     if ev is None:
1623         raise Exception("Connection timed out")
1624     if bssid not in ev:
1625         raise Exception("Unexpected network selected")
1626
1627     bssid2 = apdev[1]['bssid']
1628     params = hostapd.wpa2_params(ssid="home", passphrase="12345678")
1629     hostapd.add_ap(apdev[1]['ifname'], params)
1630
1631     dev[0].request("INTERWORKING_SELECT auto freq=2412")
1632     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
1633                             "INTERWORKING-ALREADY-CONNECTED" ], timeout=15)
1634     if ev is None:
1635         raise Exception("Connection timed out")
1636     if "INTERWORKING-ALREADY-CONNECTED" in ev:
1637         raise Exception("No roam to higher priority network")
1638     if bssid2 not in ev:
1639         raise Exception("Unexpected network selected")
1640
1641 def test_ap_hs20_network_preference2(dev, apdev):
1642     """Hotspot 2.0 network selection with preferred credential"""
1643     bssid2 = apdev[1]['bssid']
1644     params = hostapd.wpa2_params(ssid="home", passphrase="12345678")
1645     hostapd.add_ap(apdev[1]['ifname'], params)
1646
1647     dev[0].hs20_enable()
1648     values = { 'realm': "example.com",
1649                'username': "hs20-test",
1650                'password': "password",
1651                'domain': "example.com",
1652                'priority': "1" }
1653     dev[0].add_cred_values(values)
1654
1655     id = dev[0].add_network()
1656     dev[0].set_network_quoted(id, "ssid", "home")
1657     dev[0].set_network_quoted(id, "psk", "12345678")
1658     dev[0].request("ENABLE_NETWORK %s no-connect" % id)
1659
1660     dev[0].request("INTERWORKING_SELECT auto freq=2412")
1661     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
1662     if ev is None:
1663         raise Exception("Connection timed out")
1664     if bssid2 not in ev:
1665         raise Exception("Unexpected network selected")
1666
1667     bssid = apdev[0]['bssid']
1668     params = hs20_ap_params()
1669     hostapd.add_ap(apdev[0]['ifname'], params)
1670
1671     dev[0].request("INTERWORKING_SELECT auto freq=2412")
1672     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
1673                             "INTERWORKING-ALREADY-CONNECTED" ], timeout=15)
1674     if ev is None:
1675         raise Exception("Connection timed out")
1676     if "INTERWORKING-ALREADY-CONNECTED" in ev:
1677         raise Exception("No roam to higher priority network")
1678     if bssid not in ev:
1679         raise Exception("Unexpected network selected")
1680
1681 def test_ap_hs20_network_preference3(dev, apdev):
1682     """Hotspot 2.0 network selection with two credential (one preferred)"""
1683     bssid = apdev[0]['bssid']
1684     params = hs20_ap_params()
1685     hostapd.add_ap(apdev[0]['ifname'], params)
1686
1687     bssid2 = apdev[1]['bssid']
1688     params = hs20_ap_params(ssid="test-hs20b")
1689     params['nai_realm'] = "0,example.org,13[5:6],21[2:4][5:7]"
1690     hostapd.add_ap(apdev[1]['ifname'], params)
1691
1692     dev[0].hs20_enable()
1693     values = { 'realm': "example.com",
1694                'username': "hs20-test",
1695                'password': "password",
1696                'priority': "1" }
1697     dev[0].add_cred_values(values)
1698     values = { 'realm': "example.org",
1699                'username': "hs20-test",
1700                'password': "password" }
1701     id = dev[0].add_cred_values(values)
1702
1703     dev[0].request("INTERWORKING_SELECT auto freq=2412")
1704     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
1705     if ev is None:
1706         raise Exception("Connection timed out")
1707     if bssid not in ev:
1708         raise Exception("Unexpected network selected")
1709
1710     dev[0].set_cred(id, "priority", "2")
1711     dev[0].request("INTERWORKING_SELECT auto freq=2412")
1712     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
1713                             "INTERWORKING-ALREADY-CONNECTED" ], timeout=15)
1714     if ev is None:
1715         raise Exception("Connection timed out")
1716     if "INTERWORKING-ALREADY-CONNECTED" in ev:
1717         raise Exception("No roam to higher priority network")
1718     if bssid2 not in ev:
1719         raise Exception("Unexpected network selected")
1720
1721 def test_ap_hs20_network_preference4(dev, apdev):
1722     """Hotspot 2.0 network selection with username vs. SIM credential"""
1723     bssid = apdev[0]['bssid']
1724     params = hs20_ap_params()
1725     hostapd.add_ap(apdev[0]['ifname'], params)
1726
1727     bssid2 = apdev[1]['bssid']
1728     params = hs20_ap_params(ssid="test-hs20b")
1729     params['hessid'] = bssid2
1730     params['anqp_3gpp_cell_net'] = "555,444"
1731     params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org"
1732     hostapd.add_ap(apdev[1]['ifname'], params)
1733
1734     dev[0].hs20_enable()
1735     values = { 'realm': "example.com",
1736                'username': "hs20-test",
1737                'password': "password",
1738                'priority': "1" }
1739     dev[0].add_cred_values(values)
1740     values = { 'imsi': "555444-333222111",
1741                'eap': "SIM",
1742                'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123" }
1743     id = dev[0].add_cred_values(values)
1744
1745     dev[0].request("INTERWORKING_SELECT auto freq=2412")
1746     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
1747     if ev is None:
1748         raise Exception("Connection timed out")
1749     if bssid not in ev:
1750         raise Exception("Unexpected network selected")
1751
1752     dev[0].set_cred(id, "priority", "2")
1753     dev[0].request("INTERWORKING_SELECT auto freq=2412")
1754     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
1755                             "INTERWORKING-ALREADY-CONNECTED" ], timeout=15)
1756     if ev is None:
1757         raise Exception("Connection timed out")
1758     if "INTERWORKING-ALREADY-CONNECTED" in ev:
1759         raise Exception("No roam to higher priority network")
1760     if bssid2 not in ev:
1761         raise Exception("Unexpected network selected")
1762
1763 def test_ap_hs20_fetch_osu(dev, apdev):
1764     """Hotspot 2.0 OSU provider and icon fetch"""
1765     bssid = apdev[0]['bssid']
1766     params = hs20_ap_params()
1767     params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
1768     params['osu_ssid'] = '"HS 2.0 OSU open"'
1769     params['osu_method_list'] = "1"
1770     params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
1771     params['osu_icon'] = "w1fi_logo"
1772     params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
1773     params['osu_server_uri'] = "https://example.com/osu/"
1774     hostapd.add_ap(apdev[0]['ifname'], params)
1775
1776     bssid2 = apdev[1]['bssid']
1777     params = hs20_ap_params(ssid="test-hs20b")
1778     params['hessid'] = bssid2
1779     params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
1780     params['osu_ssid'] = '"HS 2.0 OSU OSEN"'
1781     params['osu_method_list'] = "0"
1782     params['osu_friendly_name'] = [ "eng:Test2 OSU", "fin:Testi2-OSU" ]
1783     params['osu_icon'] = "w1fi_logo"
1784     params['osu_service_desc'] = [ "eng:Example services2", "fin:Esimerkkipalveluja2" ]
1785     params['osu_server_uri'] = "https://example.org/osu/"
1786     hostapd.add_ap(apdev[1]['ifname'], params)
1787
1788     with open("w1fi_logo.png", "r") as f:
1789         orig_logo = f.read()
1790     dev[0].hs20_enable()
1791     dir = "/tmp/osu-fetch"
1792     if os.path.isdir(dir):
1793        files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
1794        for f in files:
1795            os.remove(dir + "/" + f)
1796     else:
1797         try:
1798             os.makedirs(dir)
1799         except:
1800             pass
1801     try:
1802         dev[0].request("SET osu_dir " + dir)
1803         dev[0].request("FETCH_OSU")
1804         icons = 0
1805         while True:
1806             ev = dev[0].wait_event(["OSU provider fetch completed",
1807                                     "RX-HS20-ANQP-ICON"], timeout=15)
1808             if ev is None:
1809                 raise Exception("Timeout on OSU fetch")
1810             if "OSU provider fetch completed" in ev:
1811                 break
1812             if "RX-HS20-ANQP-ICON" in ev:
1813                 with open(ev.split(' ')[1], "r") as f:
1814                     logo = f.read()
1815                     if logo == orig_logo:
1816                         icons += 1
1817
1818         with open(dir + "/osu-providers.txt", "r") as f:
1819             prov = f.read()
1820         if "OSU-PROVIDER " + bssid not in prov:
1821             raise Exception("Missing OSU_PROVIDER")
1822         if "OSU-PROVIDER " + bssid2 not in prov:
1823             raise Exception("Missing OSU_PROVIDER")
1824     finally:
1825         files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
1826         for f in files:
1827             os.remove(dir + "/" + f)
1828         os.rmdir(dir)
1829
1830     if icons != 2:
1831         raise Exception("Unexpected number of icons fetched")