]> git.ipfire.org Git - thirdparty/hostap.git/blob - tests/hwsim/test_ap_hs20.py
tests: ProxyARP with DGAF disabled and multicast-to-unicast conversion
[thirdparty/hostap.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 binascii
8 import struct
9 import time
10 import subprocess
11 import logging
12 logger = logging.getLogger()
13 import os
14 import os.path
15 import socket
16 import subprocess
17
18 import hostapd
19 from wlantest import Wlantest
20 from wpasupplicant import WpaSupplicant
21
22 def hs20_ap_params(ssid="test-hs20"):
23 params = hostapd.wpa2_params(ssid=ssid)
24 params['wpa_key_mgmt'] = "WPA-EAP"
25 params['ieee80211w'] = "1"
26 params['ieee8021x'] = "1"
27 params['auth_server_addr'] = "127.0.0.1"
28 params['auth_server_port'] = "1812"
29 params['auth_server_shared_secret'] = "radius"
30 params['interworking'] = "1"
31 params['access_network_type'] = "14"
32 params['internet'] = "1"
33 params['asra'] = "0"
34 params['esr'] = "0"
35 params['uesa'] = "0"
36 params['venue_group'] = "7"
37 params['venue_type'] = "1"
38 params['venue_name'] = [ "eng:Example venue", "fin:Esimerkkipaikka" ]
39 params['roaming_consortium'] = [ "112233", "1020304050", "010203040506",
40 "fedcba" ]
41 params['domain_name'] = "example.com,another.example.com"
42 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]",
43 "0,another.example.com" ]
44 params['hs20'] = "1"
45 params['hs20_wan_metrics'] = "01:8000:1000:80:240:3000"
46 params['hs20_conn_capab'] = [ "1:0:2", "6:22:1", "17:5060:0" ]
47 params['hs20_operating_class'] = "5173"
48 params['anqp_3gpp_cell_net'] = "244,91"
49 return params
50
51 def check_auto_select(dev, bssid):
52 dev.scan_for_bss(bssid, freq="2412")
53 dev.request("INTERWORKING_SELECT auto freq=2412")
54 ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
55 if ev is None:
56 raise Exception("Connection timed out")
57 if bssid not in ev:
58 raise Exception("Connected to incorrect network")
59 dev.request("REMOVE_NETWORK all")
60
61 def interworking_select(dev, bssid, type=None, no_match=False, freq=None):
62 dev.dump_monitor()
63 if bssid and freq and not no_match:
64 dev.scan_for_bss(bssid, freq=freq)
65 freq_extra = " freq=" + freq if freq else ""
66 dev.request("INTERWORKING_SELECT" + freq_extra)
67 ev = dev.wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH"],
68 timeout=15)
69 if ev is None:
70 raise Exception("Network selection timed out");
71 if no_match:
72 if "INTERWORKING-NO-MATCH" not in ev:
73 raise Exception("Unexpected network match")
74 return
75 if "INTERWORKING-NO-MATCH" in ev:
76 logger.info("Matching network not found - try again")
77 dev.dump_monitor()
78 dev.request("INTERWORKING_SELECT" + freq_extra)
79 ev = dev.wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH"],
80 timeout=15)
81 if ev is None:
82 raise Exception("Network selection timed out");
83 if "INTERWORKING-NO-MATCH" in ev:
84 raise Exception("Matching network not found")
85 if bssid and bssid not in ev:
86 raise Exception("Unexpected BSSID in match")
87 if type and "type=" + type not in ev:
88 raise Exception("Network type not recognized correctly")
89
90 def check_sp_type(dev, sp_type):
91 type = dev.get_status_field("sp_type")
92 if type is None:
93 raise Exception("sp_type not available")
94 if type != sp_type:
95 raise Exception("sp_type did not indicate home network")
96
97 def hlr_auc_gw_available():
98 if not os.path.exists("/tmp/hlr_auc_gw.sock"):
99 logger.info("No hlr_auc_gw available");
100 return False
101 if not os.path.exists("../../hostapd/hlr_auc_gw"):
102 logger.info("No hlr_auc_gw available");
103 return False
104 return True
105
106 def interworking_ext_sim_connect(dev, bssid, method):
107 dev.request("INTERWORKING_CONNECT " + bssid)
108 interworking_ext_sim_auth(dev, method)
109
110 def interworking_ext_sim_auth(dev, method):
111 ev = dev.wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=15)
112 if ev is None:
113 raise Exception("Network connected timed out")
114 if "(" + method + ")" not in ev:
115 raise Exception("Unexpected EAP method selection")
116
117 ev = dev.wait_event(["CTRL-REQ-SIM"], timeout=15)
118 if ev is None:
119 raise Exception("Wait for external SIM processing request timed out")
120 p = ev.split(':', 2)
121 if p[1] != "GSM-AUTH":
122 raise Exception("Unexpected CTRL-REQ-SIM type")
123 id = p[0].split('-')[3]
124 rand = p[2].split(' ')[0]
125
126 res = subprocess.check_output(["../../hostapd/hlr_auc_gw",
127 "-m",
128 "auth_serv/hlr_auc_gw.milenage_db",
129 "GSM-AUTH-REQ 232010000000000 " + rand])
130 if "GSM-AUTH-RESP" not in res:
131 raise Exception("Unexpected hlr_auc_gw response")
132 resp = res.split(' ')[2].rstrip()
133
134 dev.request("CTRL-RSP-SIM-" + id + ":GSM-AUTH:" + resp)
135 ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
136 if ev is None:
137 raise Exception("Connection timed out")
138
139 def interworking_connect(dev, bssid, method):
140 dev.request("INTERWORKING_CONNECT " + bssid)
141 interworking_auth(dev, method)
142
143 def interworking_auth(dev, method):
144 ev = dev.wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=15)
145 if ev is None:
146 raise Exception("Network connected timed out")
147 if "(" + method + ")" not in ev:
148 raise Exception("Unexpected EAP method selection")
149
150 ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
151 if ev is None:
152 raise Exception("Connection timed out")
153
154 def check_probe_resp(wt, bssid_unexpected, bssid_expected):
155 if bssid_unexpected:
156 count = wt.get_bss_counter("probe_response", bssid_unexpected)
157 if count > 0:
158 raise Exception("Unexpected Probe Response frame from AP")
159
160 if bssid_expected:
161 count = wt.get_bss_counter("probe_response", bssid_expected)
162 if count == 0:
163 raise Exception("No Probe Response frame from AP")
164
165 def test_ap_anqp_sharing(dev, apdev):
166 """ANQP sharing within ESS and explicit unshare"""
167 bssid = apdev[0]['bssid']
168 params = hs20_ap_params()
169 params['hessid'] = bssid
170 hostapd.add_ap(apdev[0]['ifname'], params)
171
172 bssid2 = apdev[1]['bssid']
173 params = hs20_ap_params()
174 params['hessid'] = bssid
175 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]" ]
176 hostapd.add_ap(apdev[1]['ifname'], params)
177
178 dev[0].hs20_enable()
179 id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
180 'password': "secret",
181 'domain': "example.com" })
182 logger.info("Normal network selection with shared ANQP results")
183 dev[0].scan_for_bss(bssid, freq="2412")
184 dev[0].scan_for_bss(bssid2, freq="2412")
185 interworking_select(dev[0], None, "home", freq="2412")
186 dev[0].dump_monitor()
187
188 res1 = dev[0].get_bss(bssid)
189 res2 = dev[0].get_bss(bssid2)
190 if res1['anqp_nai_realm'] != res2['anqp_nai_realm']:
191 raise Exception("ANQP results were not shared between BSSes")
192
193 logger.info("Explicit ANQP request to unshare ANQP results")
194 dev[0].request("ANQP_GET " + bssid + " 263")
195 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
196 if ev is None:
197 raise Exception("ANQP operation timed out")
198
199 dev[0].request("ANQP_GET " + bssid2 + " 263")
200 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
201 if ev is None:
202 raise Exception("ANQP operation timed out")
203
204 res1 = dev[0].get_bss(bssid)
205 res2 = dev[0].get_bss(bssid2)
206 if res1['anqp_nai_realm'] == res2['anqp_nai_realm']:
207 raise Exception("ANQP results were not unshared")
208
209 def test_ap_nai_home_realm_query(dev, apdev):
210 """NAI Home Realm Query"""
211 bssid = apdev[0]['bssid']
212 params = hs20_ap_params()
213 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]",
214 "0,another.example.org" ]
215 hostapd.add_ap(apdev[0]['ifname'], params)
216
217 dev[0].scan(freq="2412")
218 dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + bssid + " realm=example.com")
219 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
220 if ev is None:
221 raise Exception("ANQP operation timed out")
222 nai1 = dev[0].get_bss(bssid)['anqp_nai_realm']
223 dev[0].dump_monitor()
224
225 dev[0].request("ANQP_GET " + bssid + " 263")
226 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
227 if ev is None:
228 raise Exception("ANQP operation timed out")
229 nai2 = dev[0].get_bss(bssid)['anqp_nai_realm']
230
231 if len(nai1) >= len(nai2):
232 raise Exception("Unexpected NAI Realm list response lengths")
233 if "example.com".encode('hex') not in nai1:
234 raise Exception("Home realm not reported")
235 if "example.org".encode('hex') in nai1:
236 raise Exception("Non-home realm reported")
237 if "example.com".encode('hex') not in nai2:
238 raise Exception("Home realm not reported in wildcard query")
239 if "example.org".encode('hex') not in nai2:
240 raise Exception("Non-home realm not reported in wildcard query ")
241
242 def test_ap_interworking_scan_filtering(dev, apdev):
243 """Interworking scan filtering with HESSID and access network type"""
244 bssid = apdev[0]['bssid']
245 params = hs20_ap_params()
246 ssid = "test-hs20-ap1"
247 params['ssid'] = ssid
248 params['hessid'] = bssid
249 hostapd.add_ap(apdev[0]['ifname'], params)
250
251 bssid2 = apdev[1]['bssid']
252 params = hs20_ap_params()
253 ssid2 = "test-hs20-ap2"
254 params['ssid'] = ssid2
255 params['hessid'] = bssid2
256 params['access_network_type'] = "1"
257 del params['venue_group']
258 del params['venue_type']
259 hostapd.add_ap(apdev[1]['ifname'], params)
260
261 dev[0].hs20_enable()
262
263 wt = Wlantest()
264 wt.flush()
265
266 logger.info("Check probe request filtering based on HESSID")
267
268 dev[0].request("SET hessid " + bssid2)
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 access network type")
274
275 wt.clear_bss_counters(bssid)
276 wt.clear_bss_counters(bssid2)
277 dev[0].request("SET hessid 00:00:00:00:00:00")
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 00:00:00:00:00:00")
286 dev[0].request("SET access_network_type 1")
287 dev[0].scan(freq="2412")
288 time.sleep(0.03)
289 check_probe_resp(wt, bssid, bssid2)
290
291 logger.info("Check probe request filtering based on HESSID and ANT")
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 14")
297 dev[0].scan(freq="2412")
298 time.sleep(0.03)
299 check_probe_resp(wt, bssid2, bssid)
300
301 wt.clear_bss_counters(bssid)
302 wt.clear_bss_counters(bssid2)
303 dev[0].request("SET hessid " + bssid2)
304 dev[0].request("SET access_network_type 14")
305 dev[0].scan(freq="2412")
306 time.sleep(0.03)
307 check_probe_resp(wt, bssid, None)
308 check_probe_resp(wt, bssid2, None)
309
310 wt.clear_bss_counters(bssid)
311 wt.clear_bss_counters(bssid2)
312 dev[0].request("SET hessid " + bssid)
313 dev[0].request("SET access_network_type 1")
314 dev[0].scan(freq="2412")
315 time.sleep(0.03)
316 check_probe_resp(wt, bssid, None)
317 check_probe_resp(wt, bssid2, None)
318
319 def test_ap_hs20_select(dev, apdev):
320 """Hotspot 2.0 network selection"""
321 bssid = apdev[0]['bssid']
322 params = hs20_ap_params()
323 params['hessid'] = bssid
324 hostapd.add_ap(apdev[0]['ifname'], params)
325
326 dev[0].hs20_enable()
327 id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
328 'password': "secret",
329 'domain': "example.com" })
330 interworking_select(dev[0], bssid, "home")
331
332 dev[0].remove_cred(id)
333 id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
334 'password': "secret",
335 'domain': "no.match.example.com" })
336 interworking_select(dev[0], bssid, "roaming", freq="2412")
337
338 dev[0].set_cred_quoted(id, "realm", "no.match.example.com");
339 interworking_select(dev[0], bssid, no_match=True, freq="2412")
340
341 bssid2 = apdev[1]['bssid']
342 params = hs20_ap_params()
343 params['nai_realm'] = [ "0,example.org,21" ]
344 params['hessid'] = bssid2
345 params['domain_name'] = "example.org"
346 hostapd.add_ap(apdev[1]['ifname'], params)
347 dev[0].remove_cred(id)
348 id = dev[0].add_cred_values({ 'realm': "example.org", 'username': "test",
349 'password': "secret",
350 'domain': "example.org" })
351 interworking_select(dev[0], bssid2, "home", freq="2412")
352
353 def hs20_simulated_sim(dev, ap, method):
354 bssid = ap['bssid']
355 params = hs20_ap_params()
356 params['hessid'] = bssid
357 params['anqp_3gpp_cell_net'] = "555,444"
358 params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org"
359 hostapd.add_ap(ap['ifname'], params)
360
361 dev.hs20_enable()
362 dev.add_cred_values({ 'imsi': "555444-333222111", 'eap': method,
363 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"})
364 interworking_select(dev, "home", freq="2412")
365 interworking_connect(dev, bssid, method)
366 check_sp_type(dev, "home")
367
368 def test_ap_hs20_sim(dev, apdev):
369 """Hotspot 2.0 with simulated SIM and EAP-SIM"""
370 if not hlr_auc_gw_available():
371 return "skip"
372 hs20_simulated_sim(dev[0], apdev[0], "SIM")
373 dev[0].request("INTERWORKING_SELECT auto freq=2412")
374 ev = dev[0].wait_event(["INTERWORKING-ALREADY-CONNECTED"], timeout=15)
375 if ev is None:
376 raise Exception("Timeout on already-connected event")
377
378 def test_ap_hs20_aka(dev, apdev):
379 """Hotspot 2.0 with simulated USIM and EAP-AKA"""
380 if not hlr_auc_gw_available():
381 return "skip"
382 hs20_simulated_sim(dev[0], apdev[0], "AKA")
383
384 def test_ap_hs20_aka_prime(dev, apdev):
385 """Hotspot 2.0 with simulated USIM and EAP-AKA'"""
386 if not hlr_auc_gw_available():
387 return "skip"
388 hs20_simulated_sim(dev[0], apdev[0], "AKA'")
389
390 def test_ap_hs20_ext_sim(dev, apdev):
391 """Hotspot 2.0 with external SIM processing"""
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'] = "232,01"
398 params['domain_name'] = "wlan.mnc001.mcc232.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], "home", freq="2412")
405 interworking_ext_sim_connect(dev[0], bssid, "SIM")
406 check_sp_type(dev[0], "home")
407
408 def test_ap_hs20_ext_sim_roaming(dev, apdev):
409 """Hotspot 2.0 with external SIM processing in roaming network"""
410 if not hlr_auc_gw_available():
411 return "skip"
412 bssid = apdev[0]['bssid']
413 params = hs20_ap_params()
414 params['hessid'] = bssid
415 params['anqp_3gpp_cell_net'] = "244,91;310,026;232,01;234,56"
416 params['domain_name'] = "wlan.mnc091.mcc244.3gppnetwork.org"
417 hostapd.add_ap(apdev[0]['ifname'], params)
418
419 dev[0].hs20_enable()
420 dev[0].request("SET external_sim 1")
421 dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM" })
422 interworking_select(dev[0], "roaming", freq="2412")
423 interworking_ext_sim_connect(dev[0], bssid, "SIM")
424 check_sp_type(dev[0], "roaming")
425
426 def test_ap_hs20_username(dev, apdev):
427 """Hotspot 2.0 connection in username/password credential"""
428 bssid = apdev[0]['bssid']
429 params = hs20_ap_params()
430 params['hessid'] = bssid
431 params['disable_dgaf'] = '1'
432 hostapd.add_ap(apdev[0]['ifname'], params)
433
434 dev[0].hs20_enable()
435 id = dev[0].add_cred_values({ 'realm': "example.com",
436 'username': "hs20-test",
437 'password': "password",
438 'ca_cert': "auth_serv/ca.pem",
439 'domain': "example.com",
440 'update_identifier': "1234" })
441 interworking_select(dev[0], bssid, "home", freq="2412")
442 interworking_connect(dev[0], bssid, "TTLS")
443 check_sp_type(dev[0], "home")
444 status = dev[0].get_status()
445 if status['pairwise_cipher'] != "CCMP":
446 raise Exception("Unexpected pairwise cipher")
447 if status['hs20'] != "2":
448 raise Exception("Unexpected HS 2.0 support indication")
449
450 dev[1].connect("test-hs20", key_mgmt="WPA-EAP", eap="TTLS",
451 identity="hs20-test", password="password",
452 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
453 scan_freq="2412")
454
455 def test_ap_hs20_connect_api(dev, apdev):
456 """Hotspot 2.0 connection with connect API"""
457 bssid = apdev[0]['bssid']
458 params = hs20_ap_params()
459 params['hessid'] = bssid
460 params['disable_dgaf'] = '1'
461 hostapd.add_ap(apdev[0]['ifname'], params)
462
463 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
464 wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
465 wpas.hs20_enable()
466 id = wpas.add_cred_values({ 'realm': "example.com",
467 'username': "hs20-test",
468 'password': "password",
469 'ca_cert': "auth_serv/ca.pem",
470 'domain': "example.com",
471 'update_identifier': "1234" })
472 interworking_select(wpas, bssid, "home", freq="2412")
473 interworking_connect(wpas, bssid, "TTLS")
474 check_sp_type(wpas, "home")
475 status = wpas.get_status()
476 if status['pairwise_cipher'] != "CCMP":
477 raise Exception("Unexpected pairwise cipher")
478 if status['hs20'] != "2":
479 raise Exception("Unexpected HS 2.0 support indication")
480
481 def test_ap_hs20_auto_interworking(dev, apdev):
482 """Hotspot 2.0 connection with auto_interworking=1"""
483 bssid = apdev[0]['bssid']
484 params = hs20_ap_params()
485 params['hessid'] = bssid
486 params['disable_dgaf'] = '1'
487 hostapd.add_ap(apdev[0]['ifname'], params)
488
489 dev[0].hs20_enable(auto_interworking=True)
490 id = dev[0].add_cred_values({ 'realm': "example.com",
491 'username': "hs20-test",
492 'password': "password",
493 'ca_cert': "auth_serv/ca.pem",
494 'domain': "example.com",
495 'update_identifier': "1234" })
496 dev[0].request("REASSOCIATE")
497 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
498 if ev is None:
499 raise Exception("Connection timed out")
500 check_sp_type(dev[0], "home")
501 status = dev[0].get_status()
502 if status['pairwise_cipher'] != "CCMP":
503 raise Exception("Unexpected pairwise cipher")
504 if status['hs20'] != "2":
505 raise Exception("Unexpected HS 2.0 support indication")
506
507 def test_ap_hs20_auto_interworking_no_cred_match(dev, apdev):
508 """Hotspot 2.0 connection with auto_interworking=1 but no cred match"""
509 bssid = apdev[0]['bssid']
510 params = { "ssid": "test" }
511 hostapd.add_ap(apdev[0]['ifname'], params)
512
513 dev[0].hs20_enable(auto_interworking=True)
514 dev[0].add_cred_values({ 'realm': "example.com",
515 'username': "hs20-test",
516 'password': "password",
517 'ca_cert': "auth_serv/ca.pem",
518 'domain': "example.com" })
519
520 id = dev[0].connect("test", psk="12345678", only_add_network=True)
521 dev[0].request("ENABLE_NETWORK %s" % id)
522 logger.info("Verify that scanning continues when there is partial network block match")
523 for i in range(0, 2):
524 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 10)
525 if ev is None:
526 raise Exception("Scan timed out")
527 logger.info("Scan completed")
528
529 def eap_test(dev, ap, eap_params, method, user):
530 bssid = ap['bssid']
531 params = hs20_ap_params()
532 params['nai_realm'] = [ "0,example.com," + eap_params ]
533 hostapd.add_ap(ap['ifname'], params)
534
535 dev.hs20_enable()
536 dev.add_cred_values({ 'realm': "example.com",
537 'username': user,
538 'password': "password" })
539 interworking_select(dev, bssid, freq="2412")
540 interworking_connect(dev, bssid, method)
541
542 def test_ap_hs20_eap_unknown(dev, apdev):
543 """Hotspot 2.0 connection with unknown EAP method"""
544 bssid = apdev[0]['bssid']
545 params = hs20_ap_params()
546 params['nai_realm'] = "0,example.com,99"
547 hostapd.add_ap(apdev[0]['ifname'], params)
548
549 dev[0].hs20_enable()
550 dev[0].add_cred_values(default_cred())
551 interworking_select(dev[0], None, no_match=True, freq="2412")
552
553 def test_ap_hs20_eap_peap_mschapv2(dev, apdev):
554 """Hotspot 2.0 connection with PEAP/MSCHAPV2"""
555 eap_test(dev[0], apdev[0], "25[3:26]", "PEAP", "user")
556
557 def test_ap_hs20_eap_peap_default(dev, apdev):
558 """Hotspot 2.0 connection with PEAP/MSCHAPV2 (as default)"""
559 eap_test(dev[0], apdev[0], "25", "PEAP", "user")
560
561 def test_ap_hs20_eap_peap_gtc(dev, apdev):
562 """Hotspot 2.0 connection with PEAP/GTC"""
563 eap_test(dev[0], apdev[0], "25[3:6]", "PEAP", "user")
564
565 def test_ap_hs20_eap_peap_unknown(dev, apdev):
566 """Hotspot 2.0 connection with PEAP/unknown"""
567 bssid = apdev[0]['bssid']
568 params = hs20_ap_params()
569 params['nai_realm'] = "0,example.com,25[3:99]"
570 hostapd.add_ap(apdev[0]['ifname'], params)
571
572 dev[0].hs20_enable()
573 dev[0].add_cred_values(default_cred())
574 interworking_select(dev[0], None, no_match=True, freq="2412")
575
576 def test_ap_hs20_eap_ttls_chap(dev, apdev):
577 """Hotspot 2.0 connection with TTLS/CHAP"""
578 eap_test(dev[0], apdev[0], "21[2:2]", "TTLS", "chap user")
579
580 def test_ap_hs20_eap_ttls_mschap(dev, apdev):
581 """Hotspot 2.0 connection with TTLS/MSCHAP"""
582 eap_test(dev[0], apdev[0], "21[2:3]", "TTLS", "mschap user")
583
584 def test_ap_hs20_eap_ttls_eap_mschapv2(dev, apdev):
585 """Hotspot 2.0 connection with TTLS/EAP-MSCHAPv2"""
586 eap_test(dev[0], apdev[0], "21[3:26][6:7][99:99]", "TTLS", "user")
587
588 def test_ap_hs20_eap_ttls_eap_unknown(dev, apdev):
589 """Hotspot 2.0 connection with TTLS/EAP-unknown"""
590 bssid = apdev[0]['bssid']
591 params = hs20_ap_params()
592 params['nai_realm'] = "0,example.com,21[3:99]"
593 hostapd.add_ap(apdev[0]['ifname'], params)
594
595 dev[0].hs20_enable()
596 dev[0].add_cred_values(default_cred())
597 interworking_select(dev[0], None, no_match=True, freq="2412")
598
599 def test_ap_hs20_eap_ttls_eap_unsupported(dev, apdev):
600 """Hotspot 2.0 connection with TTLS/EAP-OTP(unsupported)"""
601 bssid = apdev[0]['bssid']
602 params = hs20_ap_params()
603 params['nai_realm'] = "0,example.com,21[3:5]"
604 hostapd.add_ap(apdev[0]['ifname'], params)
605
606 dev[0].hs20_enable()
607 dev[0].add_cred_values(default_cred())
608 interworking_select(dev[0], None, no_match=True, freq="2412")
609
610 def test_ap_hs20_eap_ttls_unknown(dev, apdev):
611 """Hotspot 2.0 connection with TTLS/unknown"""
612 bssid = apdev[0]['bssid']
613 params = hs20_ap_params()
614 params['nai_realm'] = "0,example.com,21[2:5]"
615 hostapd.add_ap(apdev[0]['ifname'], params)
616
617 dev[0].hs20_enable()
618 dev[0].add_cred_values(default_cred())
619 interworking_select(dev[0], None, no_match=True, freq="2412")
620
621 def test_ap_hs20_eap_fast_mschapv2(dev, apdev):
622 """Hotspot 2.0 connection with FAST/EAP-MSCHAPV2"""
623 eap_test(dev[0], apdev[0], "43[3:26]", "FAST", "user")
624
625 def test_ap_hs20_eap_fast_gtc(dev, apdev):
626 """Hotspot 2.0 connection with FAST/EAP-GTC"""
627 eap_test(dev[0], apdev[0], "43[3:6]", "FAST", "user")
628
629 def test_ap_hs20_eap_tls(dev, apdev):
630 """Hotspot 2.0 connection with EAP-TLS"""
631 bssid = apdev[0]['bssid']
632 params = hs20_ap_params()
633 params['nai_realm'] = [ "0,example.com,13[5:6]" ]
634 hostapd.add_ap(apdev[0]['ifname'], params)
635
636 dev[0].hs20_enable()
637 dev[0].add_cred_values({ 'realm': "example.com",
638 'username': "certificate-user",
639 'ca_cert': "auth_serv/ca.pem",
640 'client_cert': "auth_serv/user.pem",
641 'private_key': "auth_serv/user.key"})
642 interworking_select(dev[0], bssid, freq="2412")
643 interworking_connect(dev[0], bssid, "TLS")
644
645 def test_ap_hs20_eap_cert_unknown(dev, apdev):
646 """Hotspot 2.0 connection with certificate, but unknown EAP method"""
647 bssid = apdev[0]['bssid']
648 params = hs20_ap_params()
649 params['nai_realm'] = [ "0,example.com,99[5:6]" ]
650 hostapd.add_ap(apdev[0]['ifname'], params)
651
652 dev[0].hs20_enable()
653 dev[0].add_cred_values({ 'realm': "example.com",
654 'username': "certificate-user",
655 'ca_cert': "auth_serv/ca.pem",
656 'client_cert': "auth_serv/user.pem",
657 'private_key': "auth_serv/user.key"})
658 interworking_select(dev[0], None, no_match=True, freq="2412")
659
660 def test_ap_hs20_eap_cert_unsupported(dev, apdev):
661 """Hotspot 2.0 connection with certificate, but unsupported TTLS"""
662 bssid = apdev[0]['bssid']
663 params = hs20_ap_params()
664 params['nai_realm'] = [ "0,example.com,21[5:6]" ]
665 hostapd.add_ap(apdev[0]['ifname'], params)
666
667 dev[0].hs20_enable()
668 dev[0].add_cred_values({ 'realm': "example.com",
669 'username': "certificate-user",
670 'ca_cert': "auth_serv/ca.pem",
671 'client_cert': "auth_serv/user.pem",
672 'private_key': "auth_serv/user.key"})
673 interworking_select(dev[0], None, no_match=True, freq="2412")
674
675 def test_ap_hs20_eap_invalid_cred(dev, apdev):
676 """Hotspot 2.0 connection with invalid cred configuration"""
677 bssid = apdev[0]['bssid']
678 params = hs20_ap_params()
679 hostapd.add_ap(apdev[0]['ifname'], params)
680
681 dev[0].hs20_enable()
682 dev[0].add_cred_values({ 'realm': "example.com",
683 'username': "certificate-user",
684 'client_cert': "auth_serv/user.pem" })
685 interworking_select(dev[0], None, no_match=True, freq="2412")
686
687 def test_ap_hs20_nai_realms(dev, apdev):
688 """Hotspot 2.0 connection and multiple NAI realms and TTLS/PAP"""
689 bssid = apdev[0]['bssid']
690 params = hs20_ap_params()
691 params['hessid'] = bssid
692 params['nai_realm'] = [ "0,no.match.here;example.com;no.match.here.either,21[2:1][5:7]" ]
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': "pap user",
698 'password': "password",
699 'domain': "example.com" })
700 interworking_select(dev[0], bssid, "home", freq="2412")
701 interworking_connect(dev[0], bssid, "TTLS")
702 check_sp_type(dev[0], "home")
703
704 def test_ap_hs20_roaming_consortium(dev, apdev):
705 """Hotspot 2.0 connection based on roaming consortium match"""
706 bssid = apdev[0]['bssid']
707 params = hs20_ap_params()
708 params['hessid'] = bssid
709 hostapd.add_ap(apdev[0]['ifname'], params)
710
711 dev[0].hs20_enable()
712 for consortium in [ "112233", "1020304050", "010203040506", "fedcba" ]:
713 id = dev[0].add_cred_values({ 'username': "user",
714 'password': "password",
715 'domain': "example.com",
716 'roaming_consortium': consortium,
717 'eap': "PEAP" })
718 interworking_select(dev[0], bssid, "home", freq="2412")
719 interworking_connect(dev[0], bssid, "PEAP")
720 check_sp_type(dev[0], "home")
721 dev[0].request("INTERWORKING_SELECT auto freq=2412")
722 ev = dev[0].wait_event(["INTERWORKING-ALREADY-CONNECTED"], timeout=15)
723 if ev is None:
724 raise Exception("Timeout on already-connected event")
725 dev[0].remove_cred(id)
726
727 def test_ap_hs20_username_roaming(dev, apdev):
728 """Hotspot 2.0 connection in username/password credential (roaming)"""
729 bssid = apdev[0]['bssid']
730 params = hs20_ap_params()
731 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]",
732 "0,roaming.example.com,21[2:4][5:7]",
733 "0,another.example.com" ]
734 params['domain_name'] = "another.example.com"
735 params['hessid'] = bssid
736 hostapd.add_ap(apdev[0]['ifname'], params)
737
738 dev[0].hs20_enable()
739 id = dev[0].add_cred_values({ 'realm': "roaming.example.com",
740 'username': "hs20-test",
741 'password': "password",
742 'domain': "example.com" })
743 interworking_select(dev[0], bssid, "roaming", freq="2412")
744 interworking_connect(dev[0], bssid, "TTLS")
745 check_sp_type(dev[0], "roaming")
746
747 def test_ap_hs20_username_unknown(dev, apdev):
748 """Hotspot 2.0 connection in username/password credential (no domain in cred)"""
749 bssid = apdev[0]['bssid']
750 params = hs20_ap_params()
751 params['hessid'] = bssid
752 hostapd.add_ap(apdev[0]['ifname'], params)
753
754 dev[0].hs20_enable()
755 id = dev[0].add_cred_values({ 'realm': "example.com",
756 'username': "hs20-test",
757 'password': "password" })
758 interworking_select(dev[0], bssid, "unknown", freq="2412")
759 interworking_connect(dev[0], bssid, "TTLS")
760 check_sp_type(dev[0], "unknown")
761
762 def test_ap_hs20_username_unknown2(dev, apdev):
763 """Hotspot 2.0 connection in username/password credential (no domain advertized)"""
764 bssid = apdev[0]['bssid']
765 params = hs20_ap_params()
766 params['hessid'] = bssid
767 del params['domain_name']
768 hostapd.add_ap(apdev[0]['ifname'], params)
769
770 dev[0].hs20_enable()
771 id = dev[0].add_cred_values({ 'realm': "example.com",
772 'username': "hs20-test",
773 'password': "password",
774 'domain': "example.com" })
775 interworking_select(dev[0], bssid, "unknown", freq="2412")
776 interworking_connect(dev[0], bssid, "TTLS")
777 check_sp_type(dev[0], "unknown")
778
779 def test_ap_hs20_gas_while_associated(dev, apdev):
780 """Hotspot 2.0 connection with GAS query while associated"""
781 bssid = apdev[0]['bssid']
782 params = hs20_ap_params()
783 params['hessid'] = bssid
784 hostapd.add_ap(apdev[0]['ifname'], params)
785
786 dev[0].hs20_enable()
787 id = dev[0].add_cred_values({ 'realm': "example.com",
788 'username': "hs20-test",
789 'password': "password",
790 'domain': "example.com" })
791 interworking_select(dev[0], bssid, "home", freq="2412")
792 interworking_connect(dev[0], bssid, "TTLS")
793
794 logger.info("Verifying GAS query while associated")
795 dev[0].request("FETCH_ANQP")
796 for i in range(0, 6):
797 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
798 if ev is None:
799 raise Exception("Operation timed out")
800
801 def test_ap_hs20_gas_while_associated_with_pmf(dev, apdev):
802 """Hotspot 2.0 connection with GAS query while associated and using PMF"""
803 bssid = apdev[0]['bssid']
804 params = hs20_ap_params()
805 params['hessid'] = bssid
806 hostapd.add_ap(apdev[0]['ifname'], params)
807
808 bssid2 = apdev[1]['bssid']
809 params = hs20_ap_params()
810 params['hessid'] = bssid2
811 params['nai_realm'] = [ "0,no-match.example.org,13[5:6],21[2:4][5:7]" ]
812 hostapd.add_ap(apdev[1]['ifname'], params)
813
814 dev[0].hs20_enable()
815 dev[0].request("SET pmf 2")
816 id = dev[0].add_cred_values({ 'realm': "example.com",
817 'username': "hs20-test",
818 'password': "password",
819 'domain': "example.com" })
820 interworking_select(dev[0], bssid, "home", freq="2412")
821 interworking_connect(dev[0], bssid, "TTLS")
822
823 logger.info("Verifying GAS query while associated")
824 dev[0].request("FETCH_ANQP")
825 for i in range(0, 2 * 6):
826 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
827 if ev is None:
828 raise Exception("Operation timed out")
829
830 def test_ap_hs20_gas_frag_while_associated(dev, apdev):
831 """Hotspot 2.0 connection with fragmented GAS query while associated"""
832 bssid = apdev[0]['bssid']
833 params = hs20_ap_params()
834 params['hessid'] = bssid
835 hostapd.add_ap(apdev[0]['ifname'], params)
836 hapd = hostapd.Hostapd(apdev[0]['ifname'])
837 hapd.set("gas_frag_limit", "50")
838
839 dev[0].hs20_enable()
840 id = dev[0].add_cred_values({ 'realm': "example.com",
841 'username': "hs20-test",
842 'password': "password",
843 'domain': "example.com" })
844 interworking_select(dev[0], bssid, "home", freq="2412")
845 interworking_connect(dev[0], bssid, "TTLS")
846
847 logger.info("Verifying GAS query while associated")
848 dev[0].request("FETCH_ANQP")
849 for i in range(0, 6):
850 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
851 if ev is None:
852 raise Exception("Operation timed out")
853
854 def test_ap_hs20_multiple_connects(dev, apdev):
855 """Hotspot 2.0 connection through multiple network selections"""
856 bssid = apdev[0]['bssid']
857 params = hs20_ap_params()
858 params['hessid'] = bssid
859 hostapd.add_ap(apdev[0]['ifname'], params)
860
861 dev[0].hs20_enable()
862 values = { 'realm': "example.com",
863 'username': "hs20-test",
864 'password': "password",
865 'domain': "example.com" }
866 id = dev[0].add_cred_values(values)
867
868 dev[0].scan_for_bss(bssid, freq="2412")
869
870 for i in range(0, 3):
871 logger.info("Starting Interworking network selection")
872 dev[0].request("INTERWORKING_SELECT auto freq=2412")
873 while True:
874 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH",
875 "INTERWORKING-ALREADY-CONNECTED",
876 "CTRL-EVENT-CONNECTED"], timeout=15)
877 if ev is None:
878 raise Exception("Connection timed out")
879 if "INTERWORKING-NO-MATCH" in ev:
880 raise Exception("Matching AP not found")
881 if "CTRL-EVENT-CONNECTED" in ev:
882 break
883 if i == 2 and "INTERWORKING-ALREADY-CONNECTED" in ev:
884 break
885 if i == 0:
886 dev[0].request("DISCONNECT")
887 dev[0].dump_monitor()
888
889 networks = dev[0].list_networks()
890 if len(networks) > 1:
891 raise Exception("Duplicated network block detected")
892
893 def test_ap_hs20_disallow_aps(dev, apdev):
894 """Hotspot 2.0 connection and disallow_aps"""
895 bssid = apdev[0]['bssid']
896 params = hs20_ap_params()
897 params['hessid'] = bssid
898 hostapd.add_ap(apdev[0]['ifname'], params)
899
900 dev[0].hs20_enable()
901 values = { 'realm': "example.com",
902 'username': "hs20-test",
903 'password': "password",
904 'domain': "example.com" }
905 id = dev[0].add_cred_values(values)
906
907 dev[0].scan_for_bss(bssid, freq="2412")
908
909 logger.info("Verify disallow_aps bssid")
910 dev[0].request("SET disallow_aps bssid " + bssid.translate(None, ':'))
911 dev[0].request("INTERWORKING_SELECT auto")
912 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=15)
913 if ev is None:
914 raise Exception("Network selection timed out")
915 dev[0].dump_monitor()
916
917 logger.info("Verify disallow_aps ssid")
918 dev[0].request("SET disallow_aps ssid 746573742d68733230")
919 dev[0].request("INTERWORKING_SELECT auto freq=2412")
920 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=15)
921 if ev is None:
922 raise Exception("Network selection timed out")
923 dev[0].dump_monitor()
924
925 logger.info("Verify disallow_aps clear")
926 dev[0].request("SET disallow_aps ")
927 interworking_select(dev[0], bssid, "home", freq="2412")
928
929 dev[0].request("SET disallow_aps bssid " + bssid.translate(None, ':'))
930 ret = dev[0].request("INTERWORKING_CONNECT " + bssid)
931 if "FAIL" not in ret:
932 raise Exception("INTERWORKING_CONNECT to disallowed BSS not rejected")
933
934 def policy_test(dev, ap, values, only_one=True):
935 dev.dump_monitor()
936 if ap:
937 logger.info("Verify network selection to AP " + ap['ifname'])
938 bssid = ap['bssid']
939 dev.scan_for_bss(bssid, freq="2412")
940 else:
941 logger.info("Verify network selection")
942 bssid = None
943 dev.hs20_enable()
944 id = dev.add_cred_values(values)
945 dev.request("INTERWORKING_SELECT auto freq=2412")
946 events = []
947 while True:
948 ev = dev.wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH",
949 "INTERWORKING-BLACKLISTED",
950 "INTERWORKING-SELECTED"], timeout=15)
951 if ev is None:
952 raise Exception("Network selection timed out")
953 events.append(ev)
954 if "INTERWORKING-NO-MATCH" in ev:
955 raise Exception("Matching AP not found")
956 if bssid and only_one and "INTERWORKING-AP" in ev and bssid not in ev:
957 raise Exception("Unexpected AP claimed acceptable")
958 if "INTERWORKING-SELECTED" in ev:
959 if bssid and bssid not in ev:
960 raise Exception("Selected incorrect BSS")
961 break
962
963 ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
964 if ev is None:
965 raise Exception("Connection timed out")
966 if bssid and bssid not in ev:
967 raise Exception("Connected to incorrect BSS")
968
969 conn_bssid = dev.get_status_field("bssid")
970 if bssid and conn_bssid != bssid:
971 raise Exception("bssid information points to incorrect BSS")
972
973 dev.remove_cred(id)
974 dev.dump_monitor()
975 return events
976
977 def default_cred(domain=None):
978 cred = { 'realm': "example.com",
979 'username': "hs20-test",
980 'password': "password" }
981 if domain:
982 cred['domain'] = domain
983 return cred
984
985 def test_ap_hs20_prefer_home(dev, apdev):
986 """Hotspot 2.0 required roaming consortium"""
987 params = hs20_ap_params()
988 params['domain_name'] = "example.org"
989 hostapd.add_ap(apdev[0]['ifname'], params)
990
991 params = hs20_ap_params()
992 params['ssid'] = "test-hs20-other"
993 params['domain_name'] = "example.com"
994 hostapd.add_ap(apdev[1]['ifname'], params)
995
996 values = default_cred()
997 values['domain'] = "example.com"
998 policy_test(dev[0], apdev[1], values, only_one=False)
999 values['domain'] = "example.org"
1000 policy_test(dev[0], apdev[0], values, only_one=False)
1001
1002 def test_ap_hs20_req_roaming_consortium(dev, apdev):
1003 """Hotspot 2.0 required roaming consortium"""
1004 params = hs20_ap_params()
1005 hostapd.add_ap(apdev[0]['ifname'], params)
1006
1007 params = hs20_ap_params()
1008 params['ssid'] = "test-hs20-other"
1009 params['roaming_consortium'] = [ "223344" ]
1010 hostapd.add_ap(apdev[1]['ifname'], params)
1011
1012 values = default_cred()
1013 values['required_roaming_consortium'] = "223344"
1014 policy_test(dev[0], apdev[1], values)
1015 values['required_roaming_consortium'] = "112233"
1016 policy_test(dev[0], apdev[0], values)
1017
1018 id = dev[0].add_cred()
1019 dev[0].set_cred(id, "required_roaming_consortium", "112233")
1020 dev[0].set_cred(id, "required_roaming_consortium", "112233445566778899aabbccddeeff")
1021
1022 for val in [ "", "1", "11", "1122", "1122334", "112233445566778899aabbccddeeff00" ]:
1023 if "FAIL" not in dev[0].request('SET_CRED {} required_roaming_consortium {}'.format(id, val)):
1024 raise Exception("Invalid roaming consortium value accepted: " + val)
1025
1026 def test_ap_hs20_excluded_ssid(dev, apdev):
1027 """Hotspot 2.0 exclusion based on SSID"""
1028 params = hs20_ap_params()
1029 params['roaming_consortium'] = [ "223344" ]
1030 params['anqp_3gpp_cell_net'] = "555,444"
1031 hostapd.add_ap(apdev[0]['ifname'], params)
1032
1033 params = hs20_ap_params()
1034 params['ssid'] = "test-hs20-other"
1035 params['roaming_consortium'] = [ "223344" ]
1036 params['anqp_3gpp_cell_net'] = "555,444"
1037 hostapd.add_ap(apdev[1]['ifname'], params)
1038
1039 values = default_cred()
1040 values['excluded_ssid'] = "test-hs20"
1041 events = policy_test(dev[0], apdev[1], values)
1042 ev = [e for e in events if "INTERWORKING-BLACKLISTED " + apdev[0]['bssid'] in e]
1043 if len(ev) != 1:
1044 raise Exception("Excluded network not reported")
1045 values['excluded_ssid'] = "test-hs20-other"
1046 events = policy_test(dev[0], apdev[0], values)
1047 ev = [e for e in events if "INTERWORKING-BLACKLISTED " + apdev[1]['bssid'] in e]
1048 if len(ev) != 1:
1049 raise Exception("Excluded network not reported")
1050
1051 values = default_cred()
1052 values['roaming_consortium'] = "223344"
1053 values['eap'] = "TTLS"
1054 values['phase2'] = "auth=MSCHAPV2"
1055 values['excluded_ssid'] = "test-hs20"
1056 events = policy_test(dev[0], apdev[1], values)
1057 ev = [e for e in events if "INTERWORKING-BLACKLISTED " + apdev[0]['bssid'] in e]
1058 if len(ev) != 1:
1059 raise Exception("Excluded network not reported")
1060
1061 values = { 'imsi': "555444-333222111", 'eap': "SIM",
1062 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123",
1063 'excluded_ssid': "test-hs20" }
1064 events = policy_test(dev[0], apdev[1], values)
1065 ev = [e for e in events if "INTERWORKING-BLACKLISTED " + apdev[0]['bssid'] in e]
1066 if len(ev) != 1:
1067 raise Exception("Excluded network not reported")
1068
1069 def test_ap_hs20_roam_to_higher_prio(dev, apdev):
1070 """Hotspot 2.0 and roaming from current to higher priority network"""
1071 bssid = apdev[0]['bssid']
1072 params = hs20_ap_params(ssid="test-hs20-visited")
1073 params['domain_name'] = "visited.example.org"
1074 hostapd.add_ap(apdev[0]['ifname'], params)
1075
1076 dev[0].hs20_enable()
1077 id = dev[0].add_cred_values({ 'realm': "example.com",
1078 'username': "hs20-test",
1079 'password': "password",
1080 'domain': "example.com" })
1081 logger.info("Connect to the only network option")
1082 interworking_select(dev[0], bssid, "roaming", freq="2412")
1083 dev[0].dump_monitor()
1084 interworking_connect(dev[0], bssid, "TTLS")
1085
1086 logger.info("Start another AP (home operator) and reconnect")
1087 bssid2 = apdev[1]['bssid']
1088 params = hs20_ap_params(ssid="test-hs20-home")
1089 params['domain_name'] = "example.com"
1090 hostapd.add_ap(apdev[1]['ifname'], params)
1091
1092 dev[0].scan_for_bss(bssid2, freq="2412", force_scan=True)
1093 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1094 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH",
1095 "INTERWORKING-ALREADY-CONNECTED",
1096 "CTRL-EVENT-CONNECTED"], timeout=15)
1097 if ev is None:
1098 raise Exception("Connection timed out")
1099 if "INTERWORKING-NO-MATCH" in ev:
1100 raise Exception("Matching AP not found")
1101 if "INTERWORKING-ALREADY-CONNECTED" in ev:
1102 raise Exception("Unexpected AP selected")
1103 if bssid2 not in ev:
1104 raise Exception("Unexpected BSSID after reconnection")
1105
1106 def test_ap_hs20_domain_suffix_match(dev, apdev):
1107 """Hotspot 2.0 and domain_suffix_match"""
1108 bssid = apdev[0]['bssid']
1109 params = hs20_ap_params()
1110 hostapd.add_ap(apdev[0]['ifname'], params)
1111
1112 dev[0].hs20_enable()
1113 id = dev[0].add_cred_values({ 'realm': "example.com",
1114 'username': "hs20-test",
1115 'password': "password",
1116 'domain': "example.com",
1117 'domain_suffix_match': "w1.fi" })
1118 interworking_select(dev[0], bssid, "home", freq="2412")
1119 dev[0].dump_monitor()
1120 interworking_connect(dev[0], bssid, "TTLS")
1121 dev[0].request("REMOVE_NETWORK all")
1122 dev[0].dump_monitor()
1123
1124 dev[0].set_cred_quoted(id, "domain_suffix_match", "no-match.example.com")
1125 interworking_select(dev[0], bssid, "home", freq="2412")
1126 dev[0].dump_monitor()
1127 dev[0].request("INTERWORKING_CONNECT " + bssid)
1128 ev = dev[0].wait_event(["CTRL-EVENT-EAP-TLS-CERT-ERROR"])
1129 if ev is None:
1130 raise Exception("TLS certificate error not reported")
1131 if "Domain suffix mismatch" not in ev:
1132 raise Exception("Domain suffix mismatch not reported")
1133
1134 def test_ap_hs20_roaming_partner_preference(dev, apdev):
1135 """Hotspot 2.0 and roaming partner preference"""
1136 params = hs20_ap_params()
1137 params['domain_name'] = "roaming.example.org"
1138 hostapd.add_ap(apdev[0]['ifname'], params)
1139
1140 params = hs20_ap_params()
1141 params['ssid'] = "test-hs20-other"
1142 params['domain_name'] = "roaming.example.net"
1143 hostapd.add_ap(apdev[1]['ifname'], params)
1144
1145 logger.info("Verify default vs. specified preference")
1146 values = default_cred()
1147 values['roaming_partner'] = "roaming.example.net,1,127,*"
1148 policy_test(dev[0], apdev[1], values, only_one=False)
1149 values['roaming_partner'] = "roaming.example.net,1,129,*"
1150 policy_test(dev[0], apdev[0], values, only_one=False)
1151
1152 logger.info("Verify partial FQDN match")
1153 values['roaming_partner'] = "example.net,0,0,*"
1154 policy_test(dev[0], apdev[1], values, only_one=False)
1155 values['roaming_partner'] = "example.net,0,255,*"
1156 policy_test(dev[0], apdev[0], values, only_one=False)
1157
1158 def test_ap_hs20_max_bss_load(dev, apdev):
1159 """Hotspot 2.0 and maximum BSS load"""
1160 params = hs20_ap_params()
1161 params['bss_load_test'] = "12:200:20000"
1162 hostapd.add_ap(apdev[0]['ifname'], params)
1163
1164 params = hs20_ap_params()
1165 params['ssid'] = "test-hs20-other"
1166 params['bss_load_test'] = "5:20:10000"
1167 hostapd.add_ap(apdev[1]['ifname'], params)
1168
1169 logger.info("Verify maximum BSS load constraint")
1170 values = default_cred()
1171 values['domain'] = "example.com"
1172 values['max_bss_load'] = "100"
1173 events = policy_test(dev[0], apdev[1], values, only_one=False)
1174
1175 ev = [e for e in events if "INTERWORKING-AP " + apdev[0]['bssid'] in e]
1176 if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
1177 raise Exception("Maximum BSS Load case not noticed")
1178 ev = [e for e in events if "INTERWORKING-AP " + apdev[1]['bssid'] in e]
1179 if len(ev) != 1 or "over_max_bss_load=1" in ev[0]:
1180 raise Exception("Maximum BSS Load case reported incorrectly")
1181
1182 logger.info("Verify maximum BSS load does not prevent connection")
1183 values['max_bss_load'] = "1"
1184 events = policy_test(dev[0], None, values)
1185
1186 ev = [e for e in events if "INTERWORKING-AP " + apdev[0]['bssid'] in e]
1187 if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
1188 raise Exception("Maximum BSS Load case not noticed")
1189 ev = [e for e in events if "INTERWORKING-AP " + apdev[1]['bssid'] in e]
1190 if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
1191 raise Exception("Maximum BSS Load case not noticed")
1192
1193 def test_ap_hs20_max_bss_load2(dev, apdev):
1194 """Hotspot 2.0 and maximum BSS load with one AP not advertising"""
1195 params = hs20_ap_params()
1196 params['bss_load_test'] = "12:200:20000"
1197 hostapd.add_ap(apdev[0]['ifname'], params)
1198
1199 params = hs20_ap_params()
1200 params['ssid'] = "test-hs20-other"
1201 hostapd.add_ap(apdev[1]['ifname'], params)
1202
1203 logger.info("Verify maximum BSS load constraint with AP advertisement")
1204 values = default_cred()
1205 values['domain'] = "example.com"
1206 values['max_bss_load'] = "100"
1207 events = policy_test(dev[0], apdev[1], values, only_one=False)
1208
1209 ev = [e for e in events if "INTERWORKING-AP " + apdev[0]['bssid'] in e]
1210 if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
1211 raise Exception("Maximum BSS Load case not noticed")
1212 ev = [e for e in events if "INTERWORKING-AP " + apdev[1]['bssid'] in e]
1213 if len(ev) != 1 or "over_max_bss_load=1" in ev[0]:
1214 raise Exception("Maximum BSS Load case reported incorrectly")
1215
1216 def test_ap_hs20_multi_cred_sp_prio(dev, apdev):
1217 """Hotspot 2.0 multi-cred sp_priority"""
1218 if not hlr_auc_gw_available():
1219 return "skip"
1220 bssid = apdev[0]['bssid']
1221 params = hs20_ap_params()
1222 params['hessid'] = bssid
1223 del params['domain_name']
1224 params['anqp_3gpp_cell_net'] = "232,01"
1225 hostapd.add_ap(apdev[0]['ifname'], params)
1226
1227 dev[0].hs20_enable()
1228 dev[0].scan_for_bss(bssid, freq="2412")
1229 dev[0].request("SET external_sim 1")
1230 id1 = dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM",
1231 'provisioning_sp': "example.com",
1232 'sp_priority' :"1" })
1233 id2 = dev[0].add_cred_values({ 'realm': "example.com",
1234 'username': "hs20-test",
1235 'password': "password",
1236 'domain': "example.com",
1237 'provisioning_sp': "example.com",
1238 'sp_priority': "2" })
1239 dev[0].dump_monitor()
1240 dev[0].scan_for_bss(bssid, freq="2412")
1241 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1242 interworking_ext_sim_auth(dev[0], "SIM")
1243 check_sp_type(dev[0], "unknown")
1244 dev[0].request("REMOVE_NETWORK all")
1245
1246 dev[0].set_cred(id1, "sp_priority", "2")
1247 dev[0].set_cred(id2, "sp_priority", "1")
1248 dev[0].dump_monitor()
1249 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1250 interworking_auth(dev[0], "TTLS")
1251 check_sp_type(dev[0], "unknown")
1252
1253 def test_ap_hs20_multi_cred_sp_prio2(dev, apdev):
1254 """Hotspot 2.0 multi-cred sp_priority with two BSSes"""
1255 if not hlr_auc_gw_available():
1256 return "skip"
1257 bssid = apdev[0]['bssid']
1258 params = hs20_ap_params()
1259 params['hessid'] = bssid
1260 del params['nai_realm']
1261 del params['domain_name']
1262 params['anqp_3gpp_cell_net'] = "232,01"
1263 hostapd.add_ap(apdev[0]['ifname'], params)
1264
1265 bssid2 = apdev[1]['bssid']
1266 params = hs20_ap_params()
1267 params['ssid'] = "test-hs20-other"
1268 params['hessid'] = bssid2
1269 del params['domain_name']
1270 del params['anqp_3gpp_cell_net']
1271 hostapd.add_ap(apdev[1]['ifname'], params)
1272
1273 dev[0].hs20_enable()
1274 dev[0].request("SET external_sim 1")
1275 id1 = dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM",
1276 'provisioning_sp': "example.com",
1277 'sp_priority': "1" })
1278 id2 = dev[0].add_cred_values({ 'realm': "example.com",
1279 'username': "hs20-test",
1280 'password': "password",
1281 'domain': "example.com",
1282 'provisioning_sp': "example.com",
1283 'sp_priority': "2" })
1284 dev[0].dump_monitor()
1285 dev[0].scan_for_bss(bssid, freq="2412")
1286 dev[0].scan_for_bss(bssid2, freq="2412")
1287 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1288 interworking_ext_sim_auth(dev[0], "SIM")
1289 check_sp_type(dev[0], "unknown")
1290 conn_bssid = dev[0].get_status_field("bssid")
1291 if conn_bssid != bssid:
1292 raise Exception("Connected to incorrect BSS")
1293 dev[0].request("REMOVE_NETWORK all")
1294
1295 dev[0].set_cred(id1, "sp_priority", "2")
1296 dev[0].set_cred(id2, "sp_priority", "1")
1297 dev[0].dump_monitor()
1298 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1299 interworking_auth(dev[0], "TTLS")
1300 check_sp_type(dev[0], "unknown")
1301 conn_bssid = dev[0].get_status_field("bssid")
1302 if conn_bssid != bssid2:
1303 raise Exception("Connected to incorrect BSS")
1304
1305 def check_conn_capab_selection(dev, type, missing):
1306 dev.request("INTERWORKING_SELECT freq=2412")
1307 ev = dev.wait_event(["INTERWORKING-AP"])
1308 if ev is None:
1309 raise Exception("Network selection timed out");
1310 if "type=" + type not in ev:
1311 raise Exception("Unexpected network type")
1312 if missing and "conn_capab_missing=1" not in ev:
1313 raise Exception("conn_capab_missing not reported")
1314 if not missing and "conn_capab_missing=1" in ev:
1315 raise Exception("conn_capab_missing reported unexpectedly")
1316
1317 def conn_capab_cred(domain=None, req_conn_capab=None):
1318 cred = default_cred(domain=domain)
1319 if req_conn_capab:
1320 cred['req_conn_capab'] = req_conn_capab
1321 return cred
1322
1323 def test_ap_hs20_req_conn_capab(dev, apdev):
1324 """Hotspot 2.0 network selection with req_conn_capab"""
1325 bssid = apdev[0]['bssid']
1326 params = hs20_ap_params()
1327 hostapd.add_ap(apdev[0]['ifname'], params)
1328
1329 dev[0].hs20_enable()
1330 dev[0].scan_for_bss(bssid, freq="2412")
1331 logger.info("Not used in home network")
1332 values = conn_capab_cred(domain="example.com", req_conn_capab="6:1234")
1333 id = dev[0].add_cred_values(values)
1334 check_conn_capab_selection(dev[0], "home", False)
1335
1336 logger.info("Used in roaming network")
1337 dev[0].remove_cred(id)
1338 values = conn_capab_cred(domain="example.org", req_conn_capab="6:1234")
1339 id = dev[0].add_cred_values(values)
1340 check_conn_capab_selection(dev[0], "roaming", True)
1341
1342 logger.info("Verify that req_conn_capab does not prevent connection if no other network is available")
1343 check_auto_select(dev[0], bssid)
1344
1345 logger.info("Additional req_conn_capab checks")
1346
1347 dev[0].remove_cred(id)
1348 values = conn_capab_cred(domain="example.org", req_conn_capab="1:0")
1349 id = dev[0].add_cred_values(values)
1350 check_conn_capab_selection(dev[0], "roaming", True)
1351
1352 dev[0].remove_cred(id)
1353 values = conn_capab_cred(domain="example.org", req_conn_capab="17:5060")
1354 id = dev[0].add_cred_values(values)
1355 check_conn_capab_selection(dev[0], "roaming", True)
1356
1357 bssid2 = apdev[1]['bssid']
1358 params = hs20_ap_params(ssid="test-hs20b")
1359 params['hs20_conn_capab'] = [ "1:0:2", "6:22:1", "17:5060:0", "50:0:1" ]
1360 hostapd.add_ap(apdev[1]['ifname'], params)
1361
1362 dev[0].remove_cred(id)
1363 values = conn_capab_cred(domain="example.org", req_conn_capab="50")
1364 id = dev[0].add_cred_values(values)
1365 dev[0].set_cred(id, "req_conn_capab", "6:22")
1366 dev[0].scan_for_bss(bssid2, freq="2412")
1367 dev[0].request("INTERWORKING_SELECT freq=2412")
1368 for i in range(0, 2):
1369 ev = dev[0].wait_event(["INTERWORKING-AP"])
1370 if ev is None:
1371 raise Exception("Network selection timed out");
1372 if bssid in ev and "conn_capab_missing=1" not in ev:
1373 raise Exception("Missing protocol connection capability not reported")
1374 if bssid2 in ev and "conn_capab_missing=1" in ev:
1375 raise Exception("Protocol connection capability not reported correctly")
1376
1377 def test_ap_hs20_req_conn_capab_and_roaming_partner_preference(dev, apdev):
1378 """Hotspot 2.0 and req_conn_capab with roaming partner preference"""
1379 bssid = apdev[0]['bssid']
1380 params = hs20_ap_params()
1381 params['domain_name'] = "roaming.example.org"
1382 params['hs20_conn_capab'] = [ "1:0:2", "6:22:1", "17:5060:0", "50:0:1" ]
1383 hostapd.add_ap(apdev[0]['ifname'], params)
1384
1385 bssid2 = apdev[1]['bssid']
1386 params = hs20_ap_params(ssid="test-hs20-b")
1387 params['domain_name'] = "roaming.example.net"
1388 hostapd.add_ap(apdev[1]['ifname'], params)
1389
1390 values = default_cred()
1391 values['roaming_partner'] = "roaming.example.net,1,127,*"
1392 id = dev[0].add_cred_values(values)
1393 check_auto_select(dev[0], bssid2)
1394
1395 dev[0].set_cred(id, "req_conn_capab", "50")
1396 check_auto_select(dev[0], bssid)
1397
1398 dev[0].remove_cred(id)
1399 id = dev[0].add_cred_values(values)
1400 dev[0].set_cred(id, "req_conn_capab", "51")
1401 check_auto_select(dev[0], bssid2)
1402
1403 def check_bandwidth_selection(dev, type, below):
1404 dev.request("INTERWORKING_SELECT freq=2412")
1405 ev = dev.wait_event(["INTERWORKING-AP"])
1406 if ev is None:
1407 raise Exception("Network selection timed out");
1408 if "type=" + type not in ev:
1409 raise Exception("Unexpected network type")
1410 if below and "below_min_backhaul=1" not in ev:
1411 raise Exception("below_min_backhaul not reported")
1412 if not below and "below_min_backhaul=1" in ev:
1413 raise Exception("below_min_backhaul reported unexpectedly")
1414
1415 def bw_cred(domain=None, dl_home=None, ul_home=None, dl_roaming=None, ul_roaming=None):
1416 cred = default_cred(domain=domain)
1417 if dl_home:
1418 cred['min_dl_bandwidth_home'] = str(dl_home)
1419 if ul_home:
1420 cred['min_ul_bandwidth_home'] = str(ul_home)
1421 if dl_roaming:
1422 cred['min_dl_bandwidth_roaming'] = str(dl_roaming)
1423 if ul_roaming:
1424 cred['min_ul_bandwidth_roaming'] = str(ul_roaming)
1425 return cred
1426
1427 def test_ap_hs20_min_bandwidth_home(dev, apdev):
1428 """Hotspot 2.0 network selection with min bandwidth (home)"""
1429 bssid = apdev[0]['bssid']
1430 params = hs20_ap_params()
1431 hostapd.add_ap(apdev[0]['ifname'], params)
1432
1433 dev[0].hs20_enable()
1434 dev[0].scan_for_bss(bssid, freq="2412")
1435 values = bw_cred(domain="example.com", dl_home=5490, ul_home=58)
1436 id = dev[0].add_cred_values(values)
1437 check_bandwidth_selection(dev[0], "home", False)
1438 dev[0].remove_cred(id)
1439
1440 values = bw_cred(domain="example.com", dl_home=5491, ul_home=58)
1441 id = dev[0].add_cred_values(values)
1442 check_bandwidth_selection(dev[0], "home", True)
1443 dev[0].remove_cred(id)
1444
1445 values = bw_cred(domain="example.com", dl_home=5490, ul_home=59)
1446 id = dev[0].add_cred_values(values)
1447 check_bandwidth_selection(dev[0], "home", True)
1448 dev[0].remove_cred(id)
1449
1450 values = bw_cred(domain="example.com", dl_home=5491, ul_home=59)
1451 id = dev[0].add_cred_values(values)
1452 check_bandwidth_selection(dev[0], "home", True)
1453 check_auto_select(dev[0], bssid)
1454
1455 bssid2 = apdev[1]['bssid']
1456 params = hs20_ap_params(ssid="test-hs20-b")
1457 params['hs20_wan_metrics'] = "01:8000:1000:1:1:3000"
1458 hostapd.add_ap(apdev[1]['ifname'], params)
1459
1460 check_auto_select(dev[0], bssid2)
1461
1462 def test_ap_hs20_min_bandwidth_roaming(dev, apdev):
1463 """Hotspot 2.0 network selection with min bandwidth (roaming)"""
1464 bssid = apdev[0]['bssid']
1465 params = hs20_ap_params()
1466 hostapd.add_ap(apdev[0]['ifname'], params)
1467
1468 dev[0].hs20_enable()
1469 dev[0].scan_for_bss(bssid, freq="2412")
1470 values = bw_cred(domain="example.org", dl_roaming=5490, ul_roaming=58)
1471 id = dev[0].add_cred_values(values)
1472 check_bandwidth_selection(dev[0], "roaming", False)
1473 dev[0].remove_cred(id)
1474
1475 values = bw_cred(domain="example.org", dl_roaming=5491, ul_roaming=58)
1476 id = dev[0].add_cred_values(values)
1477 check_bandwidth_selection(dev[0], "roaming", True)
1478 dev[0].remove_cred(id)
1479
1480 values = bw_cred(domain="example.org", dl_roaming=5490, ul_roaming=59)
1481 id = dev[0].add_cred_values(values)
1482 check_bandwidth_selection(dev[0], "roaming", True)
1483 dev[0].remove_cred(id)
1484
1485 values = bw_cred(domain="example.org", dl_roaming=5491, ul_roaming=59)
1486 id = dev[0].add_cred_values(values)
1487 check_bandwidth_selection(dev[0], "roaming", True)
1488 check_auto_select(dev[0], bssid)
1489
1490 bssid2 = apdev[1]['bssid']
1491 params = hs20_ap_params(ssid="test-hs20-b")
1492 params['hs20_wan_metrics'] = "01:8000:1000:1:1:3000"
1493 hostapd.add_ap(apdev[1]['ifname'], params)
1494
1495 check_auto_select(dev[0], bssid2)
1496
1497 def test_ap_hs20_min_bandwidth_and_roaming_partner_preference(dev, apdev):
1498 """Hotspot 2.0 and minimum bandwidth with roaming partner preference"""
1499 bssid = apdev[0]['bssid']
1500 params = hs20_ap_params()
1501 params['domain_name'] = "roaming.example.org"
1502 params['hs20_wan_metrics'] = "01:8000:1000:1:1:3000"
1503 hostapd.add_ap(apdev[0]['ifname'], params)
1504
1505 bssid2 = apdev[1]['bssid']
1506 params = hs20_ap_params(ssid="test-hs20-b")
1507 params['domain_name'] = "roaming.example.net"
1508 hostapd.add_ap(apdev[1]['ifname'], params)
1509
1510 values = default_cred()
1511 values['roaming_partner'] = "roaming.example.net,1,127,*"
1512 id = dev[0].add_cred_values(values)
1513 check_auto_select(dev[0], bssid2)
1514
1515 dev[0].set_cred(id, "min_dl_bandwidth_roaming", "6000")
1516 check_auto_select(dev[0], bssid)
1517
1518 dev[0].set_cred(id, "min_dl_bandwidth_roaming", "10000")
1519 check_auto_select(dev[0], bssid2)
1520
1521 def test_ap_hs20_min_bandwidth_no_wan_metrics(dev, apdev):
1522 """Hotspot 2.0 network selection with min bandwidth but no WAN Metrics"""
1523 bssid = apdev[0]['bssid']
1524 params = hs20_ap_params()
1525 del params['hs20_wan_metrics']
1526 hostapd.add_ap(apdev[0]['ifname'], params)
1527
1528 dev[0].hs20_enable()
1529 dev[0].scan_for_bss(bssid, freq="2412")
1530 values = bw_cred(domain="example.com", dl_home=10000, ul_home=10000,
1531 dl_roaming=10000, ul_roaming=10000)
1532 dev[0].add_cred_values(values)
1533 check_bandwidth_selection(dev[0], "home", False)
1534
1535 def test_ap_hs20_deauth_req_ess(dev, apdev):
1536 """Hotspot 2.0 connection and deauthentication request for ESS"""
1537 dev[0].request("SET pmf 2")
1538 eap_test(dev[0], apdev[0], "21[3:26]", "TTLS", "user")
1539 dev[0].dump_monitor()
1540 addr = dev[0].p2p_interface_addr()
1541 hapd = hostapd.Hostapd(apdev[0]['ifname'])
1542 hapd.request("HS20_DEAUTH_REQ " + addr + " 1 120 http://example.com/")
1543 ev = dev[0].wait_event(["HS20-DEAUTH-IMMINENT-NOTICE"])
1544 if ev is None:
1545 raise Exception("Timeout on deauth imminent notice")
1546 if "1 120 http://example.com/" not in ev:
1547 raise Exception("Unexpected deauth imminent notice: " + ev)
1548 hapd.request("DEAUTHENTICATE " + addr)
1549 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"])
1550 if ev is None:
1551 raise Exception("Timeout on disconnection")
1552 if "[TEMP-DISABLED]" not in dev[0].list_networks()[0]['flags']:
1553 raise Exception("Network not marked temporarily disabled")
1554 ev = dev[0].wait_event(["SME: Trying to authenticate",
1555 "Trying to associate",
1556 "CTRL-EVENT-CONNECTED"], timeout=5)
1557 if ev is not None:
1558 raise Exception("Unexpected connection attempt")
1559
1560 def test_ap_hs20_deauth_req_bss(dev, apdev):
1561 """Hotspot 2.0 connection and deauthentication request for BSS"""
1562 dev[0].request("SET pmf 2")
1563 eap_test(dev[0], apdev[0], "21[3:26]", "TTLS", "user")
1564 dev[0].dump_monitor()
1565 addr = dev[0].p2p_interface_addr()
1566 hapd = hostapd.Hostapd(apdev[0]['ifname'])
1567 hapd.request("HS20_DEAUTH_REQ " + addr + " 0 120 http://example.com/")
1568 ev = dev[0].wait_event(["HS20-DEAUTH-IMMINENT-NOTICE"])
1569 if ev is None:
1570 raise Exception("Timeout on deauth imminent notice")
1571 if "0 120 http://example.com/" not in ev:
1572 raise Exception("Unexpected deauth imminent notice: " + ev)
1573 hapd.request("DEAUTHENTICATE " + addr + " reason=4")
1574 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"])
1575 if ev is None:
1576 raise Exception("Timeout on disconnection")
1577 if "reason=4" not in ev:
1578 raise Exception("Unexpected disconnection reason")
1579 if "[TEMP-DISABLED]" not in dev[0].list_networks()[0]['flags']:
1580 raise Exception("Network not marked temporarily disabled")
1581 ev = dev[0].wait_event(["SME: Trying to authenticate",
1582 "Trying to associate",
1583 "CTRL-EVENT-CONNECTED"], timeout=5)
1584 if ev is not None:
1585 raise Exception("Unexpected connection attempt")
1586
1587 def test_ap_hs20_deauth_req_from_radius(dev, apdev):
1588 """Hotspot 2.0 connection and deauthentication request from RADIUS"""
1589 bssid = apdev[0]['bssid']
1590 params = hs20_ap_params()
1591 params['nai_realm'] = [ "0,example.com,21[2:4]" ]
1592 params['hs20_deauth_req_timeout'] = "2"
1593 hostapd.add_ap(apdev[0]['ifname'], params)
1594
1595 dev[0].request("SET pmf 2")
1596 dev[0].hs20_enable()
1597 dev[0].add_cred_values({ 'realm': "example.com",
1598 'username': "hs20-deauth-test",
1599 'password': "password" })
1600 interworking_select(dev[0], bssid, freq="2412")
1601 interworking_connect(dev[0], bssid, "TTLS")
1602 ev = dev[0].wait_event(["HS20-DEAUTH-IMMINENT-NOTICE"], timeout=5)
1603 if ev is None:
1604 raise Exception("Timeout on deauth imminent notice")
1605 if " 1 100" not in ev:
1606 raise Exception("Unexpected deauth imminent contents")
1607 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=3)
1608 if ev is None:
1609 raise Exception("Timeout on disconnection")
1610
1611 def test_ap_hs20_remediation_required(dev, apdev):
1612 """Hotspot 2.0 connection and remediation required from RADIUS"""
1613 bssid = apdev[0]['bssid']
1614 params = hs20_ap_params()
1615 params['nai_realm'] = [ "0,example.com,21[2:4]" ]
1616 hostapd.add_ap(apdev[0]['ifname'], params)
1617
1618 dev[0].request("SET pmf 1")
1619 dev[0].hs20_enable()
1620 dev[0].add_cred_values({ 'realm': "example.com",
1621 'username': "hs20-subrem-test",
1622 'password': "password" })
1623 interworking_select(dev[0], bssid, freq="2412")
1624 interworking_connect(dev[0], bssid, "TTLS")
1625 ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=5)
1626 if ev is None:
1627 raise Exception("Timeout on subscription remediation notice")
1628 if " 1 https://example.com/" not in ev:
1629 raise Exception("Unexpected subscription remediation event contents")
1630
1631 def test_ap_hs20_remediation_required_ctrl(dev, apdev):
1632 """Hotspot 2.0 connection and subrem from ctrl_iface"""
1633 bssid = apdev[0]['bssid']
1634 addr = dev[0].p2p_dev_addr()
1635 params = hs20_ap_params()
1636 params['nai_realm'] = [ "0,example.com,21[2:4]" ]
1637 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1638
1639 dev[0].request("SET pmf 1")
1640 dev[0].hs20_enable()
1641 dev[0].add_cred_values(default_cred())
1642 interworking_select(dev[0], bssid, freq="2412")
1643 interworking_connect(dev[0], bssid, "TTLS")
1644
1645 hapd.request("HS20_WNM_NOTIF " + addr + " https://example.com/")
1646 ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=5)
1647 if ev is None:
1648 raise Exception("Timeout on subscription remediation notice")
1649 if " 1 https://example.com/" not in ev:
1650 raise Exception("Unexpected subscription remediation event contents")
1651
1652 hapd.request("HS20_WNM_NOTIF " + addr)
1653 ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=5)
1654 if ev is None:
1655 raise Exception("Timeout on subscription remediation notice")
1656 if not ev.endswith("HS20-SUBSCRIPTION-REMEDIATION "):
1657 raise Exception("Unexpected subscription remediation event contents: " + ev)
1658
1659 if "FAIL" not in hapd.request("HS20_WNM_NOTIF "):
1660 raise Exception("Unexpected HS20_WNM_NOTIF success")
1661 if "FAIL" not in hapd.request("HS20_WNM_NOTIF foo"):
1662 raise Exception("Unexpected HS20_WNM_NOTIF success")
1663 if "FAIL" not in hapd.request("HS20_WNM_NOTIF " + addr + " https://12345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678927.very.long.example.com/"):
1664 raise Exception("Unexpected HS20_WNM_NOTIF success")
1665
1666 def test_ap_hs20_session_info(dev, apdev):
1667 """Hotspot 2.0 connection and session information from RADIUS"""
1668 bssid = apdev[0]['bssid']
1669 params = hs20_ap_params()
1670 params['nai_realm'] = [ "0,example.com,21[2:4]" ]
1671 hostapd.add_ap(apdev[0]['ifname'], params)
1672
1673 dev[0].request("SET pmf 1")
1674 dev[0].hs20_enable()
1675 dev[0].add_cred_values({ 'realm': "example.com",
1676 'username': "hs20-session-info-test",
1677 'password': "password" })
1678 interworking_select(dev[0], bssid, freq="2412")
1679 interworking_connect(dev[0], bssid, "TTLS")
1680 ev = dev[0].wait_event(["ESS-DISASSOC-IMMINENT"], timeout=10)
1681 if ev is None:
1682 raise Exception("Timeout on ESS disassociation imminent notice")
1683 if " 1 59904 https://example.com/" not in ev:
1684 raise Exception("Unexpected ESS disassociation imminent event contents")
1685 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"])
1686 if ev is None:
1687 raise Exception("Scan not started")
1688 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=30)
1689 if ev is None:
1690 raise Exception("Scan not completed")
1691
1692 def test_ap_hs20_osen(dev, apdev):
1693 """Hotspot 2.0 OSEN connection"""
1694 params = { 'ssid': "osen",
1695 'osen': "1",
1696 'auth_server_addr': "127.0.0.1",
1697 'auth_server_port': "1812",
1698 'auth_server_shared_secret': "radius" }
1699 hostapd.add_ap(apdev[0]['ifname'], params)
1700
1701 dev[1].connect("osen", key_mgmt="NONE", scan_freq="2412",
1702 wait_connect=False)
1703 dev[2].connect("osen", key_mgmt="NONE", wep_key0='"hello"',
1704 scan_freq="2412", wait_connect=False)
1705 dev[0].connect("osen", proto="OSEN", key_mgmt="OSEN", pairwise="CCMP",
1706 group="GTK_NOT_USED",
1707 eap="WFA-UNAUTH-TLS", identity="osen@example.com",
1708 ca_cert="auth_serv/ca.pem",
1709 scan_freq="2412")
1710
1711 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
1712 wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
1713 wpas.connect("osen", proto="OSEN", key_mgmt="OSEN", pairwise="CCMP",
1714 group="GTK_NOT_USED",
1715 eap="WFA-UNAUTH-TLS", identity="osen@example.com",
1716 ca_cert="auth_serv/ca.pem",
1717 scan_freq="2412")
1718 wpas.request("DISCONNECT")
1719
1720 def test_ap_hs20_network_preference(dev, apdev):
1721 """Hotspot 2.0 network selection with preferred home network"""
1722 bssid = apdev[0]['bssid']
1723 params = hs20_ap_params()
1724 hostapd.add_ap(apdev[0]['ifname'], params)
1725
1726 dev[0].hs20_enable()
1727 values = { 'realm': "example.com",
1728 'username': "hs20-test",
1729 'password': "password",
1730 'domain': "example.com" }
1731 dev[0].add_cred_values(values)
1732
1733 id = dev[0].add_network()
1734 dev[0].set_network_quoted(id, "ssid", "home")
1735 dev[0].set_network_quoted(id, "psk", "12345678")
1736 dev[0].set_network(id, "priority", "1")
1737 dev[0].request("ENABLE_NETWORK %s no-connect" % id)
1738
1739 dev[0].scan_for_bss(bssid, freq="2412")
1740 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1741 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
1742 if ev is None:
1743 raise Exception("Connection timed out")
1744 if bssid not in ev:
1745 raise Exception("Unexpected network selected")
1746
1747 bssid2 = apdev[1]['bssid']
1748 params = hostapd.wpa2_params(ssid="home", passphrase="12345678")
1749 hostapd.add_ap(apdev[1]['ifname'], params)
1750
1751 dev[0].scan_for_bss(bssid2, freq="2412")
1752 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1753 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
1754 "INTERWORKING-ALREADY-CONNECTED" ], timeout=15)
1755 if ev is None:
1756 raise Exception("Connection timed out")
1757 if "INTERWORKING-ALREADY-CONNECTED" in ev:
1758 raise Exception("No roam to higher priority network")
1759 if bssid2 not in ev:
1760 raise Exception("Unexpected network selected")
1761
1762 def test_ap_hs20_network_preference2(dev, apdev):
1763 """Hotspot 2.0 network selection with preferred credential"""
1764 bssid2 = apdev[1]['bssid']
1765 params = hostapd.wpa2_params(ssid="home", passphrase="12345678")
1766 hostapd.add_ap(apdev[1]['ifname'], params)
1767
1768 dev[0].hs20_enable()
1769 values = { 'realm': "example.com",
1770 'username': "hs20-test",
1771 'password': "password",
1772 'domain': "example.com",
1773 'priority': "1" }
1774 dev[0].add_cred_values(values)
1775
1776 id = dev[0].add_network()
1777 dev[0].set_network_quoted(id, "ssid", "home")
1778 dev[0].set_network_quoted(id, "psk", "12345678")
1779 dev[0].request("ENABLE_NETWORK %s no-connect" % id)
1780
1781 dev[0].scan_for_bss(bssid2, freq="2412")
1782 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1783 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
1784 if ev is None:
1785 raise Exception("Connection timed out")
1786 if bssid2 not in ev:
1787 raise Exception("Unexpected network selected")
1788
1789 bssid = apdev[0]['bssid']
1790 params = hs20_ap_params()
1791 hostapd.add_ap(apdev[0]['ifname'], params)
1792
1793 dev[0].scan_for_bss(bssid, freq="2412")
1794 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1795 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
1796 "INTERWORKING-ALREADY-CONNECTED" ], timeout=15)
1797 if ev is None:
1798 raise Exception("Connection timed out")
1799 if "INTERWORKING-ALREADY-CONNECTED" in ev:
1800 raise Exception("No roam to higher priority network")
1801 if bssid not in ev:
1802 raise Exception("Unexpected network selected")
1803
1804 def test_ap_hs20_network_preference3(dev, apdev):
1805 """Hotspot 2.0 network selection with two credential (one preferred)"""
1806 bssid = apdev[0]['bssid']
1807 params = hs20_ap_params()
1808 hostapd.add_ap(apdev[0]['ifname'], params)
1809
1810 bssid2 = apdev[1]['bssid']
1811 params = hs20_ap_params(ssid="test-hs20b")
1812 params['nai_realm'] = "0,example.org,13[5:6],21[2:4][5:7]"
1813 hostapd.add_ap(apdev[1]['ifname'], params)
1814
1815 dev[0].hs20_enable()
1816 values = { 'realm': "example.com",
1817 'username': "hs20-test",
1818 'password': "password",
1819 'priority': "1" }
1820 dev[0].add_cred_values(values)
1821 values = { 'realm': "example.org",
1822 'username': "hs20-test",
1823 'password': "password" }
1824 id = dev[0].add_cred_values(values)
1825
1826 dev[0].scan_for_bss(bssid, freq="2412")
1827 dev[0].scan_for_bss(bssid2, freq="2412")
1828 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1829 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
1830 if ev is None:
1831 raise Exception("Connection timed out")
1832 if bssid not in ev:
1833 raise Exception("Unexpected network selected")
1834
1835 dev[0].set_cred(id, "priority", "2")
1836 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1837 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
1838 "INTERWORKING-ALREADY-CONNECTED" ], timeout=15)
1839 if ev is None:
1840 raise Exception("Connection timed out")
1841 if "INTERWORKING-ALREADY-CONNECTED" in ev:
1842 raise Exception("No roam to higher priority network")
1843 if bssid2 not in ev:
1844 raise Exception("Unexpected network selected")
1845
1846 def test_ap_hs20_network_preference4(dev, apdev):
1847 """Hotspot 2.0 network selection with username vs. SIM credential"""
1848 bssid = apdev[0]['bssid']
1849 params = hs20_ap_params()
1850 hostapd.add_ap(apdev[0]['ifname'], params)
1851
1852 bssid2 = apdev[1]['bssid']
1853 params = hs20_ap_params(ssid="test-hs20b")
1854 params['hessid'] = bssid2
1855 params['anqp_3gpp_cell_net'] = "555,444"
1856 params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org"
1857 hostapd.add_ap(apdev[1]['ifname'], params)
1858
1859 dev[0].hs20_enable()
1860 values = { 'realm': "example.com",
1861 'username': "hs20-test",
1862 'password': "password",
1863 'priority': "1" }
1864 dev[0].add_cred_values(values)
1865 values = { 'imsi': "555444-333222111",
1866 'eap': "SIM",
1867 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123" }
1868 id = dev[0].add_cred_values(values)
1869
1870 dev[0].scan_for_bss(bssid, freq="2412")
1871 dev[0].scan_for_bss(bssid2, freq="2412")
1872 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1873 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
1874 if ev is None:
1875 raise Exception("Connection timed out")
1876 if bssid not in ev:
1877 raise Exception("Unexpected network selected")
1878
1879 dev[0].set_cred(id, "priority", "2")
1880 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1881 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
1882 "INTERWORKING-ALREADY-CONNECTED" ], timeout=15)
1883 if ev is None:
1884 raise Exception("Connection timed out")
1885 if "INTERWORKING-ALREADY-CONNECTED" in ev:
1886 raise Exception("No roam to higher priority network")
1887 if bssid2 not in ev:
1888 raise Exception("Unexpected network selected")
1889
1890 def test_ap_hs20_fetch_osu(dev, apdev):
1891 """Hotspot 2.0 OSU provider and icon fetch"""
1892 bssid = apdev[0]['bssid']
1893 params = hs20_ap_params()
1894 params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
1895 params['osu_ssid'] = '"HS 2.0 OSU open"'
1896 params['osu_method_list'] = "1"
1897 params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
1898 params['osu_icon'] = "w1fi_logo"
1899 params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
1900 params['osu_server_uri'] = "https://example.com/osu/"
1901 hostapd.add_ap(apdev[0]['ifname'], params)
1902
1903 bssid2 = apdev[1]['bssid']
1904 params = hs20_ap_params(ssid="test-hs20b")
1905 params['hessid'] = bssid2
1906 params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
1907 params['osu_ssid'] = '"HS 2.0 OSU OSEN"'
1908 params['osu_method_list'] = "0"
1909 params['osu_nai'] = "osen@example.com"
1910 params['osu_friendly_name'] = [ "eng:Test2 OSU", "fin:Testi2-OSU" ]
1911 params['osu_icon'] = "w1fi_logo"
1912 params['osu_service_desc'] = [ "eng:Example services2", "fin:Esimerkkipalveluja2" ]
1913 params['osu_server_uri'] = "https://example.org/osu/"
1914 hostapd.add_ap(apdev[1]['ifname'], params)
1915
1916 with open("w1fi_logo.png", "r") as f:
1917 orig_logo = f.read()
1918 dev[0].hs20_enable()
1919 dir = "/tmp/osu-fetch"
1920 if os.path.isdir(dir):
1921 files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
1922 for f in files:
1923 os.remove(dir + "/" + f)
1924 else:
1925 try:
1926 os.makedirs(dir)
1927 except:
1928 pass
1929 try:
1930 dev[1].scan_for_bss(bssid, freq="2412")
1931 dev[0].request("SET osu_dir " + dir)
1932 dev[0].request("FETCH_OSU")
1933 if "OK" not in dev[1].request("HS20_ICON_REQUEST " + bssid + " w1fi_logo"):
1934 raise Exception("HS20_ICON_REQUEST failed")
1935 icons = 0
1936 while True:
1937 ev = dev[0].wait_event(["OSU provider fetch completed",
1938 "RX-HS20-ANQP-ICON"], timeout=15)
1939 if ev is None:
1940 raise Exception("Timeout on OSU fetch")
1941 if "OSU provider fetch completed" in ev:
1942 break
1943 if "RX-HS20-ANQP-ICON" in ev:
1944 with open(ev.split(' ')[1], "r") as f:
1945 logo = f.read()
1946 if logo == orig_logo:
1947 icons += 1
1948
1949 with open(dir + "/osu-providers.txt", "r") as f:
1950 prov = f.read()
1951 if "OSU-PROVIDER " + bssid not in prov:
1952 raise Exception("Missing OSU_PROVIDER")
1953 if "OSU-PROVIDER " + bssid2 not in prov:
1954 raise Exception("Missing OSU_PROVIDER")
1955 finally:
1956 files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
1957 for f in files:
1958 os.remove(dir + "/" + f)
1959 os.rmdir(dir)
1960
1961 if icons != 2:
1962 raise Exception("Unexpected number of icons fetched")
1963
1964 ev = dev[1].wait_event(["GAS-QUERY-START"], timeout=5)
1965 if ev is None:
1966 raise Exception("Timeout on GAS-QUERY-DONE")
1967 ev = dev[1].wait_event(["GAS-QUERY-DONE"], timeout=5)
1968 if ev is None:
1969 raise Exception("Timeout on GAS-QUERY-DONE")
1970 if "freq=2412 status_code=0 result=SUCCESS" not in ev:
1971 raise Exception("Unexpected GAS-QUERY-DONE: " + ev)
1972 ev = dev[1].wait_event(["RX-HS20-ANQP"], timeout=15)
1973 if ev is None:
1974 raise Exception("Timeout on icon fetch")
1975 if "Icon Binary File" not in ev:
1976 raise Exception("Unexpected ANQP element")
1977
1978 def test_ap_hs20_ft(dev, apdev):
1979 """Hotspot 2.0 connection with FT"""
1980 bssid = apdev[0]['bssid']
1981 params = hs20_ap_params()
1982 params['wpa_key_mgmt'] = "FT-EAP"
1983 params['nas_identifier'] = "nas1.w1.fi"
1984 params['r1_key_holder'] = "000102030405"
1985 params["mobility_domain"] = "a1b2"
1986 params["reassociation_deadline"] = "1000"
1987 hostapd.add_ap(apdev[0]['ifname'], params)
1988
1989 dev[0].hs20_enable()
1990 id = dev[0].add_cred_values({ 'realm': "example.com",
1991 'username': "hs20-test",
1992 'password': "password",
1993 'ca_cert': "auth_serv/ca.pem",
1994 'domain': "example.com",
1995 'update_identifier': "1234" })
1996 interworking_select(dev[0], bssid, "home", freq="2412")
1997 interworking_connect(dev[0], bssid, "TTLS")
1998
1999 def test_ap_hs20_remediation_sql(dev, apdev, params):
2000 """Hotspot 2.0 connection and remediation required using SQLite for user DB"""
2001 try:
2002 import sqlite3
2003 except ImportError:
2004 return "skip"
2005 dbfile = os.path.join(params['logdir'], "eap-user.db")
2006 try:
2007 os.remove(dbfile)
2008 except:
2009 pass
2010 con = sqlite3.connect(dbfile)
2011 with con:
2012 cur = con.cursor()
2013 cur.execute("CREATE TABLE users(identity TEXT PRIMARY KEY, methods TEXT, password TEXT, remediation TEXT, phase2 INTEGER)")
2014 cur.execute("CREATE TABLE wildcards(identity TEXT PRIMARY KEY, methods TEXT)")
2015 cur.execute("INSERT INTO users(identity,methods,password,phase2,remediation) VALUES ('user-mschapv2','TTLS-MSCHAPV2','password',1,'user')")
2016 cur.execute("INSERT INTO wildcards(identity,methods) VALUES ('','TTLS,TLS')")
2017 cur.execute("CREATE TABLE authlog(timestamp TEXT, session TEXT, nas_ip TEXT, username TEXT, note TEXT)")
2018
2019 try:
2020 params = { "ssid": "as", "beacon_int": "2000",
2021 "radius_server_clients": "auth_serv/radius_clients.conf",
2022 "radius_server_auth_port": '18128',
2023 "eap_server": "1",
2024 "eap_user_file": "sqlite:" + dbfile,
2025 "ca_cert": "auth_serv/ca.pem",
2026 "server_cert": "auth_serv/server.pem",
2027 "private_key": "auth_serv/server.key",
2028 "subscr_remediation_url": "https://example.org/",
2029 "subscr_remediation_method": "1" }
2030 hostapd.add_ap(apdev[1]['ifname'], params)
2031
2032 bssid = apdev[0]['bssid']
2033 params = hs20_ap_params()
2034 params['auth_server_port'] = "18128"
2035 hostapd.add_ap(apdev[0]['ifname'], params)
2036
2037 dev[0].request("SET pmf 1")
2038 dev[0].hs20_enable()
2039 id = dev[0].add_cred_values({ 'realm': "example.com",
2040 'username': "user-mschapv2",
2041 'password': "password",
2042 'ca_cert': "auth_serv/ca.pem" })
2043 interworking_select(dev[0], bssid, freq="2412")
2044 interworking_connect(dev[0], bssid, "TTLS")
2045 ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=5)
2046 if ev is None:
2047 raise Exception("Timeout on subscription remediation notice")
2048 if " 1 https://example.org/" not in ev:
2049 raise Exception("Unexpected subscription remediation event contents")
2050
2051 with con:
2052 cur = con.cursor()
2053 cur.execute("SELECT * from authlog")
2054 rows = cur.fetchall()
2055 if len(rows) < 1:
2056 raise Exception("No authlog entries")
2057
2058 finally:
2059 os.remove(dbfile)
2060
2061 def test_ap_hs20_external_selection(dev, apdev):
2062 """Hotspot 2.0 connection using external network selection and creation"""
2063 bssid = apdev[0]['bssid']
2064 params = hs20_ap_params()
2065 params['hessid'] = bssid
2066 params['disable_dgaf'] = '1'
2067 hostapd.add_ap(apdev[0]['ifname'], params)
2068
2069 dev[0].hs20_enable()
2070 dev[0].connect("test-hs20", proto="RSN", key_mgmt="WPA-EAP", eap="TTLS",
2071 identity="hs20-test", password="password",
2072 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
2073 scan_freq="2412", update_identifier="54321")
2074 if dev[0].get_status_field("hs20") != "2":
2075 raise Exception("Unexpected hs20 indication")
2076
2077 def test_ap_hs20_random_mac_addr(dev, apdev):
2078 """Hotspot 2.0 connection with random MAC address"""
2079 bssid = apdev[0]['bssid']
2080 params = hs20_ap_params()
2081 params['hessid'] = bssid
2082 params['disable_dgaf'] = '1'
2083 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
2084
2085 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
2086 wpas.interface_add("wlan5")
2087 addr = wpas.p2p_interface_addr()
2088 wpas.request("SET mac_addr 1")
2089 wpas.request("SET preassoc_mac_addr 1")
2090 wpas.request("SET rand_addr_lifetime 60")
2091 wpas.hs20_enable()
2092 wpas.scan(freq="2412", only_new=True)
2093 id = wpas.add_cred_values({ 'realm': "example.com",
2094 'username': "hs20-test",
2095 'password': "password",
2096 'ca_cert': "auth_serv/ca.pem",
2097 'domain': "example.com",
2098 'update_identifier': "1234" })
2099 interworking_select(wpas, bssid, "home", freq="2412")
2100 interworking_connect(wpas, bssid, "TTLS")
2101 addr1 = wpas.get_driver_status_field("addr")
2102 if addr == addr1:
2103 raise Exception("Did not use random MAC address")
2104
2105 sta = hapd.get_sta(addr)
2106 if sta['addr'] != "FAIL":
2107 raise Exception("Unexpected STA association with permanent address")
2108 sta = hapd.get_sta(addr1)
2109 if sta['addr'] != addr1:
2110 raise Exception("STA association with random address not found")
2111
2112 def _test_ap_hs20_proxyarp(dev, apdev):
2113 bssid = apdev[0]['bssid']
2114 params = hs20_ap_params()
2115 params['hessid'] = bssid
2116 params['disable_dgaf'] = '0'
2117 params['proxy_arp'] = '1'
2118 hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
2119 if "OK" in hapd.request("ENABLE"):
2120 raise Exception("Incomplete hostapd configuration was accepted")
2121 hapd.set("ap_isolate", "1")
2122 if "OK" in hapd.request("ENABLE"):
2123 raise Exception("Incomplete hostapd configuration was accepted")
2124 hapd.set('bridge', 'ap-br0')
2125 hapd.dump_monitor()
2126 try:
2127 hapd.enable()
2128 except:
2129 # For now, do not report failures due to missing kernel support
2130 logger.info("Could not start hostapd - assume proxyarp not supported in kernel version")
2131 return "skip"
2132 ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=10)
2133 if ev is None:
2134 raise Exception("AP startup timed out")
2135 if "AP-ENABLED" not in ev:
2136 raise Exception("AP startup failed")
2137
2138 dev[0].hs20_enable()
2139 subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
2140 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
2141
2142 id = dev[0].add_cred_values({ 'realm': "example.com",
2143 'username': "hs20-test",
2144 'password': "password",
2145 'ca_cert': "auth_serv/ca.pem",
2146 'domain': "example.com",
2147 'update_identifier': "1234" })
2148 interworking_select(dev[0], bssid, "home", freq="2412")
2149 interworking_connect(dev[0], bssid, "TTLS")
2150
2151 dev[1].connect("test-hs20", key_mgmt="WPA-EAP", eap="TTLS",
2152 identity="hs20-test", password="password",
2153 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
2154 scan_freq="2412")
2155 time.sleep(0.1)
2156
2157 addr0 = dev[0].p2p_interface_addr()
2158 addr1 = dev[1].p2p_interface_addr()
2159
2160 src_ll_opt0 = "\x01\x01" + binascii.unhexlify(addr0.replace(':',''))
2161 src_ll_opt1 = "\x01\x01" + binascii.unhexlify(addr1.replace(':',''))
2162
2163 pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
2164 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2",
2165 opt=src_ll_opt0)
2166 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
2167 raise Exception("DATA_TEST_FRAME failed")
2168
2169 pkt = build_ns(src_ll=addr1, ip_src="aaaa:bbbb:dddd::2",
2170 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:dddd::2",
2171 opt=src_ll_opt1)
2172 if "OK" not in dev[1].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
2173 raise Exception("DATA_TEST_FRAME failed")
2174
2175 pkt = build_ns(src_ll=addr1, ip_src="aaaa:bbbb:eeee::2",
2176 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:eeee::2",
2177 opt=src_ll_opt1)
2178 if "OK" not in dev[1].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
2179 raise Exception("DATA_TEST_FRAME failed")
2180
2181 matches = get_permanent_neighbors("ap-br0")
2182 logger.info("After connect: " + str(matches))
2183 if len(matches) != 3:
2184 raise Exception("Unexpected number of neighbor entries after connect")
2185 if 'aaaa:bbbb:cccc::2 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
2186 raise Exception("dev0 addr missing")
2187 if 'aaaa:bbbb:dddd::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches:
2188 raise Exception("dev1 addr(1) missing")
2189 if 'aaaa:bbbb:eeee::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches:
2190 raise Exception("dev1 addr(2) missing")
2191 dev[0].request("DISCONNECT")
2192 dev[1].request("DISCONNECT")
2193 time.sleep(0.5)
2194 matches = get_permanent_neighbors("ap-br0")
2195 logger.info("After disconnect: " + str(matches))
2196 if len(matches) > 0:
2197 raise Exception("Unexpected neighbor entries after disconnect")
2198
2199 def test_ap_hs20_proxyarp(dev, apdev):
2200 """Hotspot 2.0 and ProxyARP"""
2201 res = None
2202 try:
2203 res = _test_ap_hs20_proxyarp(dev, apdev)
2204 finally:
2205 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
2206 stderr=open('/dev/null', 'w'))
2207 subprocess.call(['brctl', 'delbr', 'ap-br0'],
2208 stderr=open('/dev/null', 'w'))
2209
2210 return res
2211
2212 def _test_ap_hs20_proxyarp_dgaf(dev, apdev, disabled):
2213 bssid = apdev[0]['bssid']
2214 params = hs20_ap_params()
2215 params['hessid'] = bssid
2216 params['disable_dgaf'] = '1' if disabled else '0'
2217 params['proxy_arp'] = '1'
2218 params['ap_isolate'] = '1'
2219 params['bridge'] = 'ap-br0'
2220 hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
2221 try:
2222 hapd.enable()
2223 except:
2224 # For now, do not report failures due to missing kernel support
2225 logger.info("Could not start hostapd - assume proxyarp not supported in kernel version")
2226 return "skip"
2227 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
2228 if ev is None:
2229 raise Exception("AP startup timed out")
2230
2231 dev[0].hs20_enable()
2232 subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
2233 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
2234
2235 id = dev[0].add_cred_values({ 'realm': "example.com",
2236 'username': "hs20-test",
2237 'password': "password",
2238 'ca_cert': "auth_serv/ca.pem",
2239 'domain': "example.com",
2240 'update_identifier': "1234" })
2241 interworking_select(dev[0], bssid, "home", freq="2412")
2242 interworking_connect(dev[0], bssid, "TTLS")
2243
2244 dev[1].connect("test-hs20", key_mgmt="WPA-EAP", eap="TTLS",
2245 identity="hs20-test", password="password",
2246 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
2247 scan_freq="2412")
2248 time.sleep(0.1)
2249
2250 addr0 = dev[0].p2p_interface_addr()
2251
2252 src_ll_opt0 = "\x01\x01" + binascii.unhexlify(addr0.replace(':',''))
2253
2254 pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
2255 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2",
2256 opt=src_ll_opt0)
2257 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
2258 raise Exception("DATA_TEST_FRAME failed")
2259
2260 pkt = build_ra(src_ll=apdev[0]['bssid'], ip_src="aaaa:bbbb:cccc::33",
2261 ip_dst="ff01::1")
2262 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
2263 raise Exception("DATA_TEST_FRAME failed")
2264
2265 pkt = build_na(src_ll=apdev[0]['bssid'], ip_src="aaaa:bbbb:cccc::44",
2266 ip_dst="ff01::1", target="aaaa:bbbb:cccc::55")
2267 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
2268 raise Exception("DATA_TEST_FRAME failed")
2269
2270 matches = get_permanent_neighbors("ap-br0")
2271 logger.info("After connect: " + str(matches))
2272 if len(matches) != 1:
2273 raise Exception("Unexpected number of neighbor entries after connect")
2274 if 'aaaa:bbbb:cccc::2 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
2275 raise Exception("dev0 addr missing")
2276 dev[0].request("DISCONNECT")
2277 dev[1].request("DISCONNECT")
2278 time.sleep(0.5)
2279 matches = get_permanent_neighbors("ap-br0")
2280 logger.info("After disconnect: " + str(matches))
2281 if len(matches) > 0:
2282 raise Exception("Unexpected neighbor entries after disconnect")
2283
2284 def test_ap_hs20_proxyarp_disable_dgaf(dev, apdev):
2285 """Hotspot 2.0 and ProxyARP with DGAF disabled"""
2286 res = None
2287 try:
2288 res = _test_ap_hs20_proxyarp_dgaf(dev, apdev, True)
2289 finally:
2290 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
2291 stderr=open('/dev/null', 'w'))
2292 subprocess.call(['brctl', 'delbr', 'ap-br0'],
2293 stderr=open('/dev/null', 'w'))
2294
2295 return res
2296
2297 def test_ap_hs20_proxyarp_enable_dgaf(dev, apdev):
2298 """Hotspot 2.0 and ProxyARP with DGAF enabled"""
2299 res = None
2300 try:
2301 res = _test_ap_hs20_proxyarp_dgaf(dev, apdev, False)
2302 finally:
2303 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
2304 stderr=open('/dev/null', 'w'))
2305 subprocess.call(['brctl', 'delbr', 'ap-br0'],
2306 stderr=open('/dev/null', 'w'))
2307
2308 return res
2309
2310 def ip_checksum(buf):
2311 sum = 0
2312 if len(buf) & 0x01:
2313 buf += '\0x00'
2314 for i in range(0, len(buf), 2):
2315 val, = struct.unpack('H', buf[i:i+2])
2316 sum += val
2317 while (sum >> 16):
2318 sum = (sum & 0xffff) + (sum >> 16)
2319 return struct.pack('H', ~sum & 0xffff)
2320
2321 def build_icmpv6(ipv6_addrs, type, code, payload):
2322 start = struct.pack("BB", type, code)
2323 end = payload
2324 icmp = start + '\x00\x00' + end
2325 pseudo = ipv6_addrs + struct.pack(">LBBBB", len(icmp), 0, 0, 0, 58)
2326 csum = ip_checksum(pseudo + icmp)
2327 return start + csum + end
2328
2329 def build_ra(src_ll, ip_src, ip_dst, cur_hop_limit=0, router_lifetime=0,
2330 reachable_time=0, retrans_timer=0, opt=None):
2331 link_mc = binascii.unhexlify("3333ff000002")
2332 _src_ll = binascii.unhexlify(src_ll.replace(':',''))
2333 proto = '\x86\xdd'
2334 ehdr = link_mc + _src_ll + proto
2335 _ip_src = socket.inet_pton(socket.AF_INET6, ip_src)
2336 _ip_dst = socket.inet_pton(socket.AF_INET6, ip_dst)
2337
2338 adv = struct.pack('>BBHLL', cur_hop_limit, 0, router_lifetime,
2339 reachable_time, retrans_timer)
2340 if opt:
2341 payload = adv + opt
2342 else:
2343 payload = adv
2344 icmp = build_icmpv6(_ip_src + _ip_dst, 134, 0, payload)
2345
2346 ipv6 = struct.pack('>BBBBHBB', 0x60, 0, 0, 0, len(icmp), 58, 255)
2347 ipv6 += _ip_src + _ip_dst
2348
2349 return ehdr + ipv6 + icmp
2350
2351 def build_ns(src_ll, ip_src, ip_dst, target, opt=None):
2352 link_mc = binascii.unhexlify("3333ff000002")
2353 _src_ll = binascii.unhexlify(src_ll.replace(':',''))
2354 proto = '\x86\xdd'
2355 ehdr = link_mc + _src_ll + proto
2356 _ip_src = socket.inet_pton(socket.AF_INET6, ip_src)
2357 _ip_dst = socket.inet_pton(socket.AF_INET6, ip_dst)
2358
2359 reserved = '\x00\x00\x00\x00'
2360 _target = socket.inet_pton(socket.AF_INET6, target)
2361 if opt:
2362 payload = reserved + _target + opt
2363 else:
2364 payload = reserved + _target
2365 icmp = build_icmpv6(_ip_src + _ip_dst, 135, 0, payload)
2366
2367 ipv6 = struct.pack('>BBBBHBB', 0x60, 0, 0, 0, len(icmp), 58, 255)
2368 ipv6 += _ip_src + _ip_dst
2369
2370 return ehdr + ipv6 + icmp
2371
2372 def build_na(src_ll, ip_src, ip_dst, target, opt=None):
2373 link_mc = binascii.unhexlify("3333ff000002")
2374 _src_ll = binascii.unhexlify(src_ll.replace(':',''))
2375 proto = '\x86\xdd'
2376 ehdr = link_mc + _src_ll + proto
2377 _ip_src = socket.inet_pton(socket.AF_INET6, ip_src)
2378 _ip_dst = socket.inet_pton(socket.AF_INET6, ip_dst)
2379
2380 reserved = '\x00\x00\x00\x00'
2381 _target = socket.inet_pton(socket.AF_INET6, target)
2382 if opt:
2383 payload = reserved + _target + opt
2384 else:
2385 payload = reserved + _target
2386 icmp = build_icmpv6(_ip_src + _ip_dst, 136, 0, payload)
2387
2388 ipv6 = struct.pack('>BBBBHBB', 0x60, 0, 0, 0, len(icmp), 58, 255)
2389 ipv6 += _ip_src + _ip_dst
2390
2391 return ehdr + ipv6 + icmp
2392
2393 def get_permanent_neighbors(ifname):
2394 cmd = subprocess.Popen(['ip', 'nei'], stdout=subprocess.PIPE)
2395 res = cmd.stdout.read()
2396 cmd.stdout.close()
2397 return [ line for line in res.splitlines() if "PERMANENT" in line and ifname in line ]
2398
2399 def _test_proxyarp_open(dev, apdev):
2400 bssid = apdev[0]['bssid']
2401 params = { 'ssid': 'open' }
2402 params['proxy_arp'] = '1'
2403 hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
2404 hapd.set("ap_isolate", "1")
2405 hapd.set('bridge', 'ap-br0')
2406 hapd.dump_monitor()
2407 try:
2408 hapd.enable()
2409 except:
2410 # For now, do not report failures due to missing kernel support
2411 logger.info("Could not start hostapd - assume proxyarp not supported in kernel version")
2412 return "skip"
2413 ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=10)
2414 if ev is None:
2415 raise Exception("AP startup timed out")
2416 if "AP-ENABLED" not in ev:
2417 raise Exception("AP startup failed")
2418
2419 subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
2420 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
2421
2422 dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
2423 dev[1].connect("open", key_mgmt="NONE", scan_freq="2412")
2424 time.sleep(0.1)
2425
2426 addr0 = dev[0].p2p_interface_addr()
2427 addr1 = dev[1].p2p_interface_addr()
2428
2429 src_ll_opt0 = "\x01\x01" + binascii.unhexlify(addr0.replace(':',''))
2430 src_ll_opt1 = "\x01\x01" + binascii.unhexlify(addr1.replace(':',''))
2431
2432 # DAD NS
2433 pkt = build_ns(src_ll=addr0, ip_src="::", ip_dst="ff02::1:ff00:2",
2434 target="aaaa:bbbb:cccc::2", opt=src_ll_opt0)
2435 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
2436 raise Exception("DATA_TEST_FRAME failed")
2437
2438 pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
2439 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2",
2440 opt=src_ll_opt0)
2441 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
2442 raise Exception("DATA_TEST_FRAME failed")
2443 # test frame without source link-layer address option
2444 pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
2445 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2")
2446 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
2447 raise Exception("DATA_TEST_FRAME failed")
2448 # test frame with bogus option
2449 pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
2450 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2",
2451 opt="\x70\x01\x01\x02\x03\x04\x05\x05")
2452 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
2453 raise Exception("DATA_TEST_FRAME failed")
2454 # test frame with truncated source link-layer address option
2455 pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
2456 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2",
2457 opt="\x01\x01\x01\x02\x03\x04")
2458 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
2459 raise Exception("DATA_TEST_FRAME failed")
2460 # test frame with foreign source link-layer address option
2461 pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
2462 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2",
2463 opt="\x01\x01\x01\x02\x03\x04\x05\x06")
2464 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
2465 raise Exception("DATA_TEST_FRAME failed")
2466
2467 pkt = build_ns(src_ll=addr1, ip_src="aaaa:bbbb:dddd::2",
2468 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:dddd::2",
2469 opt=src_ll_opt1)
2470 if "OK" not in dev[1].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
2471 raise Exception("DATA_TEST_FRAME failed")
2472
2473 pkt = build_ns(src_ll=addr1, ip_src="aaaa:bbbb:eeee::2",
2474 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:eeee::2",
2475 opt=src_ll_opt1)
2476 if "OK" not in dev[1].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
2477 raise Exception("DATA_TEST_FRAME failed")
2478 # another copy for additional code coverage
2479 if "OK" not in dev[1].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
2480 raise Exception("DATA_TEST_FRAME failed")
2481
2482 matches = get_permanent_neighbors("ap-br0")
2483 logger.info("After connect: " + str(matches))
2484 if len(matches) != 3:
2485 raise Exception("Unexpected number of neighbor entries after connect")
2486 if 'aaaa:bbbb:cccc::2 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
2487 raise Exception("dev0 addr missing")
2488 if 'aaaa:bbbb:dddd::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches:
2489 raise Exception("dev1 addr(1) missing")
2490 if 'aaaa:bbbb:eeee::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches:
2491 raise Exception("dev1 addr(2) missing")
2492
2493 dev[0].request("DISCONNECT")
2494 dev[1].request("DISCONNECT")
2495 time.sleep(0.5)
2496 matches = get_permanent_neighbors("ap-br0")
2497 logger.info("After disconnect: " + str(matches))
2498 if len(matches) > 0:
2499 raise Exception("Unexpected neighbor entries after disconnect")
2500
2501 def test_proxyarp_open(dev, apdev):
2502 """ProxyARP with open network"""
2503 res = None
2504 try:
2505 res = _test_proxyarp_open(dev, apdev)
2506 finally:
2507 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
2508 stderr=open('/dev/null', 'w'))
2509 subprocess.call(['brctl', 'delbr', 'ap-br0'],
2510 stderr=open('/dev/null', 'w'))
2511
2512 return res