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