]> git.ipfire.org Git - thirdparty/hostap.git/blob - tests/hwsim/test_ap_hs20.py
tests: Use python3 compatible "except" statement
[thirdparty/hostap.git] / tests / hwsim / test_ap_hs20.py
1 # Hotspot 2.0 tests
2 # Copyright (c) 2013-2015, 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 from remotehost import remote_compatible
8 import base64
9 import binascii
10 import struct
11 import time
12 import logging
13 logger = logging.getLogger()
14 import os
15 import os.path
16 import socket
17 import subprocess
18
19 import hostapd
20 from utils import HwsimSkip, skip_with_fips, alloc_fail, fail_test, wait_fail_trigger
21 import hwsim_utils
22 from tshark import run_tshark
23 from wlantest import Wlantest
24 from wpasupplicant import WpaSupplicant
25 from test_ap_eap import check_eap_capa, check_domain_match_full
26 from test_gas import gas_rx, parse_gas, action_response, anqp_initial_resp, send_gas_resp, ACTION_CATEG_PUBLIC, GAS_INITIAL_RESPONSE
27
28 def hs20_ap_params(ssid="test-hs20"):
29 params = hostapd.wpa2_params(ssid=ssid)
30 params['wpa_key_mgmt'] = "WPA-EAP"
31 params['ieee80211w'] = "1"
32 params['ieee8021x'] = "1"
33 params['auth_server_addr'] = "127.0.0.1"
34 params['auth_server_port'] = "1812"
35 params['auth_server_shared_secret'] = "radius"
36 params['interworking'] = "1"
37 params['access_network_type'] = "14"
38 params['internet'] = "1"
39 params['asra'] = "0"
40 params['esr'] = "0"
41 params['uesa'] = "0"
42 params['venue_group'] = "7"
43 params['venue_type'] = "1"
44 params['venue_name'] = [ "eng:Example venue", "fin:Esimerkkipaikka" ]
45 params['roaming_consortium'] = [ "112233", "1020304050", "010203040506",
46 "fedcba" ]
47 params['domain_name'] = "example.com,another.example.com"
48 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]",
49 "0,another.example.com" ]
50 params['hs20'] = "1"
51 params['hs20_wan_metrics'] = "01:8000:1000:80:240:3000"
52 params['hs20_conn_capab'] = [ "1:0:2", "6:22:1", "17:5060:0" ]
53 params['hs20_operating_class'] = "5173"
54 params['anqp_3gpp_cell_net'] = "244,91"
55 return params
56
57 def check_auto_select(dev, bssid):
58 dev.scan_for_bss(bssid, freq="2412")
59 dev.request("INTERWORKING_SELECT auto freq=2412")
60 ev = dev.wait_connected(timeout=15)
61 if bssid not in ev:
62 raise Exception("Connected to incorrect network")
63 dev.request("REMOVE_NETWORK all")
64 dev.wait_disconnected()
65 dev.dump_monitor()
66
67 def interworking_select(dev, bssid, type=None, no_match=False, freq=None):
68 dev.dump_monitor()
69 if bssid and freq and not no_match:
70 dev.scan_for_bss(bssid, freq=freq)
71 freq_extra = " freq=" + str(freq) if freq else ""
72 dev.request("INTERWORKING_SELECT" + freq_extra)
73 ev = dev.wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH"],
74 timeout=15)
75 if ev is None:
76 raise Exception("Network selection timed out")
77 if no_match:
78 if "INTERWORKING-NO-MATCH" not in ev:
79 raise Exception("Unexpected network match")
80 return
81 if "INTERWORKING-NO-MATCH" in ev:
82 logger.info("Matching network not found - try again")
83 dev.dump_monitor()
84 dev.request("INTERWORKING_SELECT" + freq_extra)
85 ev = dev.wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH"],
86 timeout=15)
87 if ev is None:
88 raise Exception("Network selection timed out")
89 if "INTERWORKING-NO-MATCH" in ev:
90 raise Exception("Matching network not found")
91 if bssid and bssid not in ev:
92 raise Exception("Unexpected BSSID in match")
93 if type and "type=" + type not in ev:
94 raise Exception("Network type not recognized correctly")
95
96 def check_sp_type(dev, sp_type):
97 type = dev.get_status_field("sp_type")
98 if type is None:
99 raise Exception("sp_type not available")
100 if type != sp_type:
101 raise Exception("sp_type did not indicate %s network" % sp_type)
102
103 def hlr_auc_gw_available():
104 if not os.path.exists("/tmp/hlr_auc_gw.sock"):
105 raise HwsimSkip("No hlr_auc_gw socket available")
106 if not os.path.exists("../../hostapd/hlr_auc_gw"):
107 raise HwsimSkip("No hlr_auc_gw available")
108
109 def interworking_ext_sim_connect(dev, bssid, method):
110 dev.request("INTERWORKING_CONNECT " + bssid)
111 interworking_ext_sim_auth(dev, method)
112
113 def interworking_ext_sim_auth(dev, method):
114 ev = dev.wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=15)
115 if ev is None:
116 raise Exception("Network connected timed out")
117 if "(" + method + ")" not in ev:
118 raise Exception("Unexpected EAP method selection")
119
120 ev = dev.wait_event(["CTRL-REQ-SIM"], timeout=15)
121 if ev is None:
122 raise Exception("Wait for external SIM processing request timed out")
123 p = ev.split(':', 2)
124 if p[1] != "GSM-AUTH":
125 raise Exception("Unexpected CTRL-REQ-SIM type")
126 id = p[0].split('-')[3]
127 rand = p[2].split(' ')[0]
128
129 res = subprocess.check_output(["../../hostapd/hlr_auc_gw",
130 "-m",
131 "auth_serv/hlr_auc_gw.milenage_db",
132 "GSM-AUTH-REQ 232010000000000 " + rand])
133 if "GSM-AUTH-RESP" not in res:
134 raise Exception("Unexpected hlr_auc_gw response")
135 resp = res.split(' ')[2].rstrip()
136
137 dev.request("CTRL-RSP-SIM-" + id + ":GSM-AUTH:" + resp)
138 dev.wait_connected(timeout=15)
139
140 def interworking_connect(dev, bssid, method):
141 dev.request("INTERWORKING_CONNECT " + bssid)
142 interworking_auth(dev, method)
143
144 def interworking_auth(dev, method):
145 ev = dev.wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=15)
146 if ev is None:
147 raise Exception("Network connected timed out")
148 if "(" + method + ")" not in ev:
149 raise Exception("Unexpected EAP method selection")
150
151 dev.wait_connected(timeout=15)
152
153 def check_probe_resp(wt, bssid_unexpected, bssid_expected):
154 if bssid_unexpected:
155 count = wt.get_bss_counter("probe_response", bssid_unexpected)
156 if count > 0:
157 raise Exception("Unexpected Probe Response frame from AP")
158
159 if bssid_expected:
160 count = wt.get_bss_counter("probe_response", bssid_expected)
161 if count == 0:
162 raise Exception("No Probe Response frame from AP")
163
164 def test_ap_anqp_sharing(dev, apdev):
165 """ANQP sharing within ESS and explicit unshare"""
166 check_eap_capa(dev[0], "MSCHAPV2")
167 dev[0].flush_scan_cache()
168
169 bssid = apdev[0]['bssid']
170 params = hs20_ap_params()
171 params['hessid'] = bssid
172 hostapd.add_ap(apdev[0], params)
173
174 bssid2 = apdev[1]['bssid']
175 params = hs20_ap_params()
176 params['hessid'] = bssid
177 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]" ]
178 hostapd.add_ap(apdev[1], params)
179
180 dev[0].hs20_enable()
181 id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
182 'password': "secret",
183 'domain': "example.com" })
184 logger.info("Normal network selection with shared ANQP results")
185 dev[0].scan_for_bss(bssid, freq="2412")
186 dev[0].scan_for_bss(bssid2, freq="2412")
187 interworking_select(dev[0], None, "home", freq="2412")
188 dev[0].dump_monitor()
189 state = dev[0].get_status_field('wpa_state')
190 if state != "DISCONNECTED":
191 raise Exception("Unexpected wpa_state after INTERWORKING_SELECT: " + state)
192
193 logger.debug("BSS entries:\n" + dev[0].request("BSS RANGE=ALL"))
194 res1 = dev[0].get_bss(bssid)
195 res2 = dev[0].get_bss(bssid2)
196 if 'anqp_nai_realm' not in res1:
197 raise Exception("anqp_nai_realm not found for AP1")
198 if 'anqp_nai_realm' not in res2:
199 raise Exception("anqp_nai_realm not found for AP2")
200 if res1['anqp_nai_realm'] != res2['anqp_nai_realm']:
201 raise Exception("ANQP results were not shared between BSSes")
202
203 logger.info("Explicit ANQP request to unshare ANQP results")
204 dev[0].request("ANQP_GET " + bssid + " 263")
205 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
206 if ev is None:
207 raise Exception("ANQP operation timed out")
208
209 dev[0].request("ANQP_GET " + bssid2 + " 263")
210 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
211 if ev is None:
212 raise Exception("ANQP operation timed out")
213
214 res1 = dev[0].get_bss(bssid)
215 res2 = dev[0].get_bss(bssid2)
216 if res1['anqp_nai_realm'] == res2['anqp_nai_realm']:
217 raise Exception("ANQP results were not unshared")
218
219 def test_ap_anqp_domain_id(dev, apdev):
220 """ANQP Domain ID"""
221 check_eap_capa(dev[0], "MSCHAPV2")
222 dev[0].flush_scan_cache()
223
224 bssid = apdev[0]['bssid']
225 params = hs20_ap_params()
226 params['hessid'] = bssid
227 params['anqp_domain_id'] = '1234'
228 hostapd.add_ap(apdev[0], params)
229
230 bssid2 = apdev[1]['bssid']
231 params = hs20_ap_params()
232 params['hessid'] = bssid
233 params['anqp_domain_id'] = '1234'
234 hostapd.add_ap(apdev[1], params)
235
236 dev[0].hs20_enable()
237 id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
238 'password': "secret",
239 'domain': "example.com" })
240 dev[0].scan_for_bss(bssid, freq="2412")
241 dev[0].scan_for_bss(bssid2, freq="2412")
242 interworking_select(dev[0], None, "home", freq="2412")
243
244 def test_ap_anqp_no_sharing_diff_ess(dev, apdev):
245 """ANQP no sharing between ESSs"""
246 check_eap_capa(dev[0], "MSCHAPV2")
247 dev[0].flush_scan_cache()
248
249 bssid = apdev[0]['bssid']
250 params = hs20_ap_params()
251 params['hessid'] = bssid
252 hostapd.add_ap(apdev[0], params)
253
254 bssid2 = apdev[1]['bssid']
255 params = hs20_ap_params(ssid="test-hs20-another")
256 params['hessid'] = bssid
257 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]" ]
258 hostapd.add_ap(apdev[1], params)
259
260 dev[0].hs20_enable()
261 id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
262 'password': "secret",
263 'domain': "example.com" })
264 logger.info("Normal network selection with shared ANQP results")
265 dev[0].scan_for_bss(bssid, freq="2412")
266 dev[0].scan_for_bss(bssid2, freq="2412")
267 interworking_select(dev[0], None, "home", freq="2412")
268
269 def test_ap_anqp_no_sharing_missing_info(dev, apdev):
270 """ANQP no sharing due to missing information"""
271 check_eap_capa(dev[0], "MSCHAPV2")
272 dev[0].flush_scan_cache()
273
274 bssid = apdev[0]['bssid']
275 params = hs20_ap_params()
276 params['hessid'] = bssid
277 del params['roaming_consortium']
278 del params['domain_name']
279 del params['anqp_3gpp_cell_net']
280 del params['nai_realm']
281 hostapd.add_ap(apdev[0], params)
282
283 bssid2 = apdev[1]['bssid']
284 params = hs20_ap_params()
285 params['hessid'] = bssid
286 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]" ]
287 hostapd.add_ap(apdev[1], params)
288
289 dev[0].hs20_enable()
290 id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
291 'password': "secret",
292 'domain': "example.com" })
293 logger.info("Normal network selection with shared ANQP results")
294 dev[0].scan_for_bss(bssid, freq="2412")
295 dev[0].scan_for_bss(bssid2, freq="2412")
296 interworking_select(dev[0], None, "home", freq="2412")
297
298 def test_ap_anqp_sharing_oom(dev, apdev):
299 """ANQP sharing within ESS and explicit unshare OOM"""
300 check_eap_capa(dev[0], "MSCHAPV2")
301 dev[0].flush_scan_cache()
302
303 bssid = apdev[0]['bssid']
304 params = hs20_ap_params()
305 params['hessid'] = bssid
306 hostapd.add_ap(apdev[0], params)
307
308 bssid2 = apdev[1]['bssid']
309 params = hs20_ap_params()
310 params['hessid'] = bssid
311 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]" ]
312 hostapd.add_ap(apdev[1], params)
313
314 dev[0].hs20_enable()
315 id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
316 'password': "secret",
317 'domain': "example.com" })
318 dev[0].scan_for_bss(bssid, freq="2412")
319 dev[0].scan_for_bss(bssid2, freq="2412")
320 interworking_select(dev[0], None, "home", freq="2412")
321 dev[0].dump_monitor()
322
323 with alloc_fail(dev[0], 1, "wpa_bss_anqp_clone"):
324 dev[0].request("ANQP_GET " + bssid + " 263")
325 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
326 if ev is None:
327 raise Exception("ANQP operation timed out")
328
329 def test_ap_nai_home_realm_query(dev, apdev):
330 """NAI Home Realm Query"""
331 check_eap_capa(dev[0], "MSCHAPV2")
332 bssid = apdev[0]['bssid']
333 params = hs20_ap_params()
334 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]",
335 "0,another.example.org" ]
336 hostapd.add_ap(apdev[0], params)
337
338 dev[0].scan(freq="2412")
339 dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + bssid + " realm=example.com")
340 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
341 if ev is None:
342 raise Exception("ANQP operation timed out")
343 nai1 = dev[0].get_bss(bssid)['anqp_nai_realm']
344 dev[0].dump_monitor()
345
346 dev[0].request("ANQP_GET " + bssid + " 263")
347 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
348 if ev is None:
349 raise Exception("ANQP operation timed out")
350 nai2 = dev[0].get_bss(bssid)['anqp_nai_realm']
351
352 if len(nai1) >= len(nai2):
353 raise Exception("Unexpected NAI Realm list response lengths")
354 if "example.com".encode('hex') not in nai1:
355 raise Exception("Home realm not reported")
356 if "example.org".encode('hex') in nai1:
357 raise Exception("Non-home realm reported")
358 if "example.com".encode('hex') not in nai2:
359 raise Exception("Home realm not reported in wildcard query")
360 if "example.org".encode('hex') not in nai2:
361 raise Exception("Non-home realm not reported in wildcard query ")
362
363 cmds = [ "foo",
364 "00:11:22:33:44:55 123",
365 "00:11:22:33:44:55 qq" ]
366 for cmd in cmds:
367 if "FAIL" not in dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + cmd):
368 raise Exception("Invalid HS20_GET_NAI_HOME_REALM_LIST accepted: " + cmd)
369
370 dev[0].dump_monitor()
371 if "OK" not in dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + bssid):
372 raise Exception("HS20_GET_NAI_HOME_REALM_LIST failed")
373 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
374 if ev is None:
375 raise Exception("ANQP operation timed out")
376 ev = dev[0].wait_event(["RX-ANQP"], timeout=0.1)
377 if ev is not None:
378 raise Exception("Unexpected ANQP response: " + ev)
379
380 dev[0].dump_monitor()
381 if "OK" not in dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + bssid + " 01000b6578616d706c652e636f6d"):
382 raise Exception("HS20_GET_NAI_HOME_REALM_LIST failed")
383 ev = dev[0].wait_event(["RX-ANQP"], timeout=10)
384 if ev is None:
385 raise Exception("No ANQP response")
386 if "NAI Realm list" not in ev:
387 raise Exception("Missing NAI Realm list: " + ev)
388
389 dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
390 'password': "secret",
391 'domain': "example.com" })
392 dev[0].dump_monitor()
393 if "OK" not in dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + bssid):
394 raise Exception("HS20_GET_NAI_HOME_REALM_LIST failed")
395 ev = dev[0].wait_event(["RX-ANQP"], timeout=10)
396 if ev is None:
397 raise Exception("No ANQP response")
398 if "NAI Realm list" not in ev:
399 raise Exception("Missing NAI Realm list: " + ev)
400
401 @remote_compatible
402 def test_ap_interworking_scan_filtering(dev, apdev):
403 """Interworking scan filtering with HESSID and access network type"""
404 try:
405 _test_ap_interworking_scan_filtering(dev, apdev)
406 finally:
407 dev[0].request("SET hessid 00:00:00:00:00:00")
408 dev[0].request("SET access_network_type 15")
409
410 def _test_ap_interworking_scan_filtering(dev, apdev):
411 bssid = apdev[0]['bssid']
412 params = hs20_ap_params()
413 ssid = "test-hs20-ap1"
414 params['ssid'] = ssid
415 params['hessid'] = bssid
416 hapd0 = hostapd.add_ap(apdev[0], params)
417
418 bssid2 = apdev[1]['bssid']
419 params = hs20_ap_params()
420 ssid2 = "test-hs20-ap2"
421 params['ssid'] = ssid2
422 params['hessid'] = bssid2
423 params['access_network_type'] = "1"
424 del params['venue_group']
425 del params['venue_type']
426 hostapd.add_ap(apdev[1], params)
427
428 dev[0].hs20_enable()
429
430 Wlantest.setup(hapd0)
431 wt = Wlantest()
432 wt.flush()
433
434 # Make sure wlantest has seen both BSSs to avoid issues in trying to clear
435 # counters for non-existing BSS.
436 dev[0].scan_for_bss(bssid, freq="2412")
437 dev[0].scan_for_bss(bssid2, freq="2412")
438 wt.clear_bss_counters(bssid)
439 wt.clear_bss_counters(bssid2)
440
441 logger.info("Check probe request filtering based on HESSID")
442
443 dev[0].request("SET hessid " + bssid2)
444 dev[0].scan(freq="2412")
445 time.sleep(0.03)
446 check_probe_resp(wt, bssid, bssid2)
447
448 logger.info("Check probe request filtering based on access network type")
449
450 wt.clear_bss_counters(bssid)
451 wt.clear_bss_counters(bssid2)
452 dev[0].request("SET hessid 00:00:00:00:00:00")
453 dev[0].request("SET access_network_type 14")
454 dev[0].scan(freq="2412")
455 time.sleep(0.03)
456 check_probe_resp(wt, bssid2, bssid)
457
458 wt.clear_bss_counters(bssid)
459 wt.clear_bss_counters(bssid2)
460 dev[0].request("SET hessid 00:00:00:00:00:00")
461 dev[0].request("SET access_network_type 1")
462 dev[0].scan(freq="2412")
463 time.sleep(0.03)
464 check_probe_resp(wt, bssid, bssid2)
465
466 logger.info("Check probe request filtering based on HESSID and ANT")
467
468 wt.clear_bss_counters(bssid)
469 wt.clear_bss_counters(bssid2)
470 dev[0].request("SET hessid " + bssid)
471 dev[0].request("SET access_network_type 14")
472 dev[0].scan(freq="2412")
473 time.sleep(0.03)
474 check_probe_resp(wt, bssid2, bssid)
475
476 wt.clear_bss_counters(bssid)
477 wt.clear_bss_counters(bssid2)
478 dev[0].request("SET hessid " + bssid2)
479 dev[0].request("SET access_network_type 14")
480 dev[0].scan(freq="2412")
481 time.sleep(0.03)
482 check_probe_resp(wt, bssid, None)
483 check_probe_resp(wt, bssid2, None)
484
485 wt.clear_bss_counters(bssid)
486 wt.clear_bss_counters(bssid2)
487 dev[0].request("SET hessid " + bssid)
488 dev[0].request("SET access_network_type 1")
489 dev[0].scan(freq="2412")
490 time.sleep(0.03)
491 check_probe_resp(wt, bssid, None)
492 check_probe_resp(wt, bssid2, None)
493
494 def test_ap_hs20_select(dev, apdev):
495 """Hotspot 2.0 network selection"""
496 bssid = apdev[0]['bssid']
497 params = hs20_ap_params()
498 params['hessid'] = bssid
499 hostapd.add_ap(apdev[0], params)
500
501 dev[0].hs20_enable()
502 id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
503 'password': "secret",
504 'domain': "example.com" })
505 interworking_select(dev[0], bssid, "home")
506
507 dev[0].remove_cred(id)
508 id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
509 'password': "secret",
510 'domain': "no.match.example.com" })
511 interworking_select(dev[0], bssid, "roaming", freq="2412")
512
513 dev[0].set_cred_quoted(id, "realm", "no.match.example.com")
514 interworking_select(dev[0], bssid, no_match=True, freq="2412")
515
516 res = dev[0].request("SCAN_RESULTS")
517 if "[HS20]" not in res:
518 raise Exception("HS20 flag missing from scan results: " + res)
519
520 bssid2 = apdev[1]['bssid']
521 params = hs20_ap_params()
522 params['nai_realm'] = [ "0,example.org,21" ]
523 params['hessid'] = bssid2
524 params['domain_name'] = "example.org"
525 hostapd.add_ap(apdev[1], params)
526 dev[0].remove_cred(id)
527 id = dev[0].add_cred_values({ 'realm': "example.org", 'username': "test",
528 'password': "secret",
529 'domain': "example.org" })
530 interworking_select(dev[0], bssid2, "home", freq="2412")
531
532 def hs20_simulated_sim(dev, ap, method):
533 bssid = ap['bssid']
534 params = hs20_ap_params()
535 params['hessid'] = bssid
536 params['anqp_3gpp_cell_net'] = "555,444"
537 params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org"
538 hostapd.add_ap(ap, params)
539
540 dev.hs20_enable()
541 dev.add_cred_values({ 'imsi': "555444-333222111", 'eap': method,
542 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"})
543 interworking_select(dev, bssid, "home", freq="2412")
544 interworking_connect(dev, bssid, method)
545 check_sp_type(dev, "home")
546
547 def test_ap_hs20_sim(dev, apdev):
548 """Hotspot 2.0 with simulated SIM and EAP-SIM"""
549 hlr_auc_gw_available()
550 hs20_simulated_sim(dev[0], apdev[0], "SIM")
551 dev[0].request("INTERWORKING_SELECT auto freq=2412")
552 ev = dev[0].wait_event(["INTERWORKING-ALREADY-CONNECTED"], timeout=15)
553 if ev is None:
554 raise Exception("Timeout on already-connected event")
555
556 def test_ap_hs20_sim_invalid(dev, apdev):
557 """Hotspot 2.0 with simulated SIM and EAP-SIM - invalid IMSI"""
558 hlr_auc_gw_available()
559 bssid = apdev[0]['bssid']
560 params = hs20_ap_params()
561 params['hessid'] = bssid
562 params['anqp_3gpp_cell_net'] = "555,444"
563 params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org"
564 hostapd.add_ap(apdev[0], params)
565
566 dev[0].hs20_enable()
567 dev[0].add_cred_values({ 'imsi': "555444-3332221110", 'eap': "SIM",
568 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"})
569 # This hits "No valid IMSI available" in build_root_nai()
570 interworking_select(dev[0], bssid, freq="2412")
571
572 def test_ap_hs20_sim_oom(dev, apdev):
573 """Hotspot 2.0 with simulated SIM and EAP-SIM - OOM"""
574 hlr_auc_gw_available()
575 bssid = apdev[0]['bssid']
576 params = hs20_ap_params()
577 params['hessid'] = bssid
578 params['anqp_3gpp_cell_net'] = "555,444"
579 params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org"
580 hostapd.add_ap(apdev[0], params)
581
582 dev[0].hs20_enable()
583 dev[0].add_cred_values({ 'imsi': "555444-333222111", 'eap': "SIM",
584 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"})
585 dev[0].scan_for_bss(bssid, freq=2412)
586 interworking_select(dev[0], bssid, freq="2412")
587
588 with alloc_fail(dev[0], 1, "wpa_config_add_network;interworking_connect_3gpp"):
589 dev[0].request("INTERWORKING_CONNECT " + bssid)
590 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
591
592 with alloc_fail(dev[0], 1, "=interworking_connect_3gpp"):
593 dev[0].request("INTERWORKING_CONNECT " + bssid)
594 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
595
596 def test_ap_hs20_aka(dev, apdev):
597 """Hotspot 2.0 with simulated USIM and EAP-AKA"""
598 hlr_auc_gw_available()
599 hs20_simulated_sim(dev[0], apdev[0], "AKA")
600
601 def test_ap_hs20_aka_prime(dev, apdev):
602 """Hotspot 2.0 with simulated USIM and EAP-AKA'"""
603 hlr_auc_gw_available()
604 hs20_simulated_sim(dev[0], apdev[0], "AKA'")
605
606 def test_ap_hs20_ext_sim(dev, apdev):
607 """Hotspot 2.0 with external SIM processing"""
608 hlr_auc_gw_available()
609 bssid = apdev[0]['bssid']
610 params = hs20_ap_params()
611 params['hessid'] = bssid
612 params['anqp_3gpp_cell_net'] = "232,01"
613 params['domain_name'] = "wlan.mnc001.mcc232.3gppnetwork.org"
614 hostapd.add_ap(apdev[0], params)
615
616 dev[0].hs20_enable()
617 try:
618 dev[0].request("SET external_sim 1")
619 dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM" })
620 interworking_select(dev[0], bssid, "home", freq="2412")
621 interworking_ext_sim_connect(dev[0], bssid, "SIM")
622 check_sp_type(dev[0], "home")
623 finally:
624 dev[0].request("SET external_sim 0")
625
626 def test_ap_hs20_ext_sim_roaming(dev, apdev):
627 """Hotspot 2.0 with external SIM processing in roaming network"""
628 hlr_auc_gw_available()
629 bssid = apdev[0]['bssid']
630 params = hs20_ap_params()
631 params['hessid'] = bssid
632 params['anqp_3gpp_cell_net'] = "244,91;310,026;232,01;234,56"
633 params['domain_name'] = "wlan.mnc091.mcc244.3gppnetwork.org"
634 hostapd.add_ap(apdev[0], params)
635
636 dev[0].hs20_enable()
637 try:
638 dev[0].request("SET external_sim 1")
639 dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM" })
640 interworking_select(dev[0], bssid, "roaming", freq="2412")
641 interworking_ext_sim_connect(dev[0], bssid, "SIM")
642 check_sp_type(dev[0], "roaming")
643 finally:
644 dev[0].request("SET external_sim 0")
645
646 def test_ap_hs20_username(dev, apdev):
647 """Hotspot 2.0 connection in username/password credential"""
648 check_eap_capa(dev[0], "MSCHAPV2")
649 bssid = apdev[0]['bssid']
650 params = hs20_ap_params()
651 params['hessid'] = bssid
652 params['disable_dgaf'] = '1'
653 hostapd.add_ap(apdev[0], params)
654
655 dev[0].hs20_enable()
656 id = dev[0].add_cred_values({ 'realm': "example.com",
657 'username': "hs20-test",
658 'password': "password",
659 'ca_cert': "auth_serv/ca.pem",
660 'domain': "example.com",
661 'update_identifier': "1234" })
662 interworking_select(dev[0], bssid, "home", freq="2412")
663 interworking_connect(dev[0], bssid, "TTLS")
664 check_sp_type(dev[0], "home")
665 status = dev[0].get_status()
666 if status['pairwise_cipher'] != "CCMP":
667 raise Exception("Unexpected pairwise cipher")
668 if status['hs20'] != "3":
669 raise Exception("Unexpected HS 2.0 support indication")
670
671 dev[1].connect("test-hs20", key_mgmt="WPA-EAP", eap="TTLS",
672 identity="hs20-test", password="password",
673 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
674 scan_freq="2412")
675
676 def test_ap_hs20_connect_api(dev, apdev):
677 """Hotspot 2.0 connection with connect API"""
678 check_eap_capa(dev[0], "MSCHAPV2")
679 bssid = apdev[0]['bssid']
680 params = hs20_ap_params()
681 params['hessid'] = bssid
682 params['disable_dgaf'] = '1'
683 hostapd.add_ap(apdev[0], params)
684
685 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
686 wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
687 wpas.hs20_enable()
688 wpas.flush_scan_cache()
689 id = wpas.add_cred_values({ 'realm': "example.com",
690 'username': "hs20-test",
691 'password': "password",
692 'ca_cert': "auth_serv/ca.pem",
693 'domain': "example.com",
694 'update_identifier': "1234" })
695 interworking_select(wpas, bssid, "home", freq="2412")
696 interworking_connect(wpas, bssid, "TTLS")
697 check_sp_type(wpas, "home")
698 status = wpas.get_status()
699 if status['pairwise_cipher'] != "CCMP":
700 raise Exception("Unexpected pairwise cipher")
701 if status['hs20'] != "3":
702 raise Exception("Unexpected HS 2.0 support indication")
703
704 def test_ap_hs20_auto_interworking(dev, apdev):
705 """Hotspot 2.0 connection with auto_interworking=1"""
706 check_eap_capa(dev[0], "MSCHAPV2")
707 bssid = apdev[0]['bssid']
708 params = hs20_ap_params()
709 params['hessid'] = bssid
710 params['disable_dgaf'] = '1'
711 hostapd.add_ap(apdev[0], params)
712
713 dev[0].hs20_enable(auto_interworking=True)
714 id = dev[0].add_cred_values({ 'realm': "example.com",
715 'username': "hs20-test",
716 'password': "password",
717 'ca_cert': "auth_serv/ca.pem",
718 'domain': "example.com",
719 'update_identifier': "1234" })
720 dev[0].request("REASSOCIATE")
721 dev[0].wait_connected(timeout=15)
722 check_sp_type(dev[0], "home")
723 status = dev[0].get_status()
724 if status['pairwise_cipher'] != "CCMP":
725 raise Exception("Unexpected pairwise cipher")
726 if status['hs20'] != "3":
727 raise Exception("Unexpected HS 2.0 support indication")
728
729 @remote_compatible
730 def test_ap_hs20_auto_interworking_no_match(dev, apdev):
731 """Hotspot 2.0 connection with auto_interworking=1 and no matching network"""
732 hapd = hostapd.add_ap(apdev[0], { "ssid": "mismatch" })
733
734 dev[0].hs20_enable(auto_interworking=True)
735 id = dev[0].connect("mismatch", psk="12345678", scan_freq="2412",
736 only_add_network=True)
737 dev[0].request("ENABLE_NETWORK " + str(id) + " no-connect")
738
739 id = dev[0].add_cred_values({ 'realm': "example.com",
740 'username': "hs20-test",
741 'password': "password",
742 'ca_cert': "auth_serv/ca.pem",
743 'domain': "example.com",
744 'update_identifier': "1234" })
745 dev[0].request("INTERWORKING_SELECT auto freq=2412")
746 time.sleep(0.1)
747 dev[0].dump_monitor()
748 for i in range(5):
749 logger.info("start ping")
750 if "PONG" not in dev[0].ctrl.request("PING", timeout=2):
751 raise Exception("PING failed")
752 logger.info("ping done")
753 fetch = 0
754 scan = 0
755 for j in range(15):
756 ev = dev[0].wait_event([ "ANQP fetch completed",
757 "CTRL-EVENT-SCAN-RESULTS" ], timeout=0.05)
758 if ev is None:
759 break
760 if "ANQP fetch completed" in ev:
761 fetch += 1
762 else:
763 scan += 1
764 if fetch > 2 * scan + 3:
765 raise Exception("Too many ANQP fetch iterations")
766 dev[0].dump_monitor()
767 dev[0].request("DISCONNECT")
768
769 @remote_compatible
770 def test_ap_hs20_auto_interworking_no_cred_match(dev, apdev):
771 """Hotspot 2.0 connection with auto_interworking=1 but no cred match"""
772 bssid = apdev[0]['bssid']
773 params = { "ssid": "test" }
774 hostapd.add_ap(apdev[0], params)
775
776 dev[0].hs20_enable(auto_interworking=True)
777 dev[0].add_cred_values({ 'realm': "example.com",
778 'username': "hs20-test",
779 'password': "password",
780 'ca_cert': "auth_serv/ca.pem",
781 'domain': "example.com" })
782
783 id = dev[0].connect("test", psk="12345678", only_add_network=True)
784 dev[0].request("ENABLE_NETWORK %s" % id)
785 logger.info("Verify that scanning continues when there is partial network block match")
786 for i in range(0, 2):
787 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 10)
788 if ev is None:
789 raise Exception("Scan timed out")
790 logger.info("Scan completed")
791
792 def eap_test(dev, ap, eap_params, method, user, release=0):
793 bssid = ap['bssid']
794 params = hs20_ap_params()
795 params['nai_realm'] = [ "0,example.com," + eap_params ]
796 if release > 0:
797 params['hs20_release'] = str(release)
798 hostapd.add_ap(ap, params)
799
800 dev.hs20_enable()
801 dev.add_cred_values({ 'realm': "example.com",
802 'ca_cert': "auth_serv/ca.pem",
803 'username': user,
804 'password': "password" })
805 interworking_select(dev, bssid, freq="2412")
806 interworking_connect(dev, bssid, method)
807
808 @remote_compatible
809 def test_ap_hs20_eap_unknown(dev, apdev):
810 """Hotspot 2.0 connection with unknown EAP method"""
811 bssid = apdev[0]['bssid']
812 params = hs20_ap_params()
813 params['nai_realm'] = "0,example.com,99"
814 hostapd.add_ap(apdev[0], params)
815
816 dev[0].hs20_enable()
817 dev[0].add_cred_values(default_cred())
818 interworking_select(dev[0], None, no_match=True, freq="2412")
819
820 def test_ap_hs20_eap_peap_mschapv2(dev, apdev):
821 """Hotspot 2.0 connection with PEAP/MSCHAPV2"""
822 check_eap_capa(dev[0], "MSCHAPV2")
823 eap_test(dev[0], apdev[0], "25[3:26]", "PEAP", "user")
824
825 def test_ap_hs20_eap_peap_default(dev, apdev):
826 """Hotspot 2.0 connection with PEAP/MSCHAPV2 (as default)"""
827 check_eap_capa(dev[0], "MSCHAPV2")
828 eap_test(dev[0], apdev[0], "25", "PEAP", "user")
829
830 def test_ap_hs20_eap_peap_gtc(dev, apdev):
831 """Hotspot 2.0 connection with PEAP/GTC"""
832 eap_test(dev[0], apdev[0], "25[3:6]", "PEAP", "user")
833
834 @remote_compatible
835 def test_ap_hs20_eap_peap_unknown(dev, apdev):
836 """Hotspot 2.0 connection with PEAP/unknown"""
837 bssid = apdev[0]['bssid']
838 params = hs20_ap_params()
839 params['nai_realm'] = "0,example.com,25[3:99]"
840 hostapd.add_ap(apdev[0], params)
841
842 dev[0].hs20_enable()
843 dev[0].add_cred_values(default_cred())
844 interworking_select(dev[0], None, no_match=True, freq="2412")
845
846 def test_ap_hs20_eap_ttls_chap(dev, apdev):
847 """Hotspot 2.0 connection with TTLS/CHAP"""
848 skip_with_fips(dev[0])
849 eap_test(dev[0], apdev[0], "21[2:2]", "TTLS", "chap user")
850
851 def test_ap_hs20_eap_ttls_mschap(dev, apdev):
852 """Hotspot 2.0 connection with TTLS/MSCHAP"""
853 skip_with_fips(dev[0])
854 eap_test(dev[0], apdev[0], "21[2:3]", "TTLS", "mschap user")
855
856 def test_ap_hs20_eap_ttls_default(dev, apdev):
857 """Hotspot 2.0 connection with TTLS/default"""
858 skip_with_fips(dev[0])
859 eap_test(dev[0], apdev[0], "21", "TTLS", "hs20-test")
860
861 def test_ap_hs20_eap_ttls_eap_mschapv2(dev, apdev):
862 """Hotspot 2.0 connection with TTLS/EAP-MSCHAPv2"""
863 check_eap_capa(dev[0], "MSCHAPV2")
864 eap_test(dev[0], apdev[0], "21[3:26][6:7][99:99]", "TTLS", "user")
865
866 @remote_compatible
867 def test_ap_hs20_eap_ttls_eap_unknown(dev, apdev):
868 """Hotspot 2.0 connection with TTLS/EAP-unknown"""
869 bssid = apdev[0]['bssid']
870 params = hs20_ap_params()
871 params['nai_realm'] = "0,example.com,21[3:99]"
872 hostapd.add_ap(apdev[0], params)
873
874 dev[0].hs20_enable()
875 dev[0].add_cred_values(default_cred())
876 interworking_select(dev[0], None, no_match=True, freq="2412")
877
878 @remote_compatible
879 def test_ap_hs20_eap_ttls_eap_unsupported(dev, apdev):
880 """Hotspot 2.0 connection with TTLS/EAP-OTP(unsupported)"""
881 bssid = apdev[0]['bssid']
882 params = hs20_ap_params()
883 params['nai_realm'] = "0,example.com,21[3:5]"
884 hostapd.add_ap(apdev[0], params)
885
886 dev[0].hs20_enable()
887 dev[0].add_cred_values(default_cred())
888 interworking_select(dev[0], None, no_match=True, freq="2412")
889
890 @remote_compatible
891 def test_ap_hs20_eap_ttls_unknown(dev, apdev):
892 """Hotspot 2.0 connection with TTLS/unknown"""
893 bssid = apdev[0]['bssid']
894 params = hs20_ap_params()
895 params['nai_realm'] = "0,example.com,21[2:5]"
896 hostapd.add_ap(apdev[0], params)
897
898 dev[0].hs20_enable()
899 dev[0].add_cred_values(default_cred())
900 interworking_select(dev[0], None, no_match=True, freq="2412")
901
902 def test_ap_hs20_eap_fast_mschapv2(dev, apdev):
903 """Hotspot 2.0 connection with FAST/EAP-MSCHAPV2"""
904 check_eap_capa(dev[0], "FAST")
905 eap_test(dev[0], apdev[0], "43[3:26]", "FAST", "user")
906
907 def test_ap_hs20_eap_fast_gtc(dev, apdev):
908 """Hotspot 2.0 connection with FAST/EAP-GTC"""
909 check_eap_capa(dev[0], "FAST")
910 eap_test(dev[0], apdev[0], "43[3:6]", "FAST", "user")
911
912 def test_ap_hs20_eap_tls(dev, apdev):
913 """Hotspot 2.0 connection with EAP-TLS"""
914 bssid = apdev[0]['bssid']
915 params = hs20_ap_params()
916 params['nai_realm'] = [ "0,example.com,13[5:6]" ]
917 hostapd.add_ap(apdev[0], params)
918
919 dev[0].hs20_enable()
920 dev[0].add_cred_values({ 'realm': "example.com",
921 'username': "certificate-user",
922 'ca_cert': "auth_serv/ca.pem",
923 'client_cert': "auth_serv/user.pem",
924 'private_key': "auth_serv/user.key"})
925 interworking_select(dev[0], bssid, freq="2412")
926 interworking_connect(dev[0], bssid, "TLS")
927
928 @remote_compatible
929 def test_ap_hs20_eap_cert_unknown(dev, apdev):
930 """Hotspot 2.0 connection with certificate, but unknown EAP method"""
931 bssid = apdev[0]['bssid']
932 params = hs20_ap_params()
933 params['nai_realm'] = [ "0,example.com,99[5:6]" ]
934 hostapd.add_ap(apdev[0], params)
935
936 dev[0].hs20_enable()
937 dev[0].add_cred_values({ 'realm': "example.com",
938 'username': "certificate-user",
939 'ca_cert': "auth_serv/ca.pem",
940 'client_cert': "auth_serv/user.pem",
941 'private_key': "auth_serv/user.key"})
942 interworking_select(dev[0], None, no_match=True, freq="2412")
943
944 @remote_compatible
945 def test_ap_hs20_eap_cert_unsupported(dev, apdev):
946 """Hotspot 2.0 connection with certificate, but unsupported TTLS"""
947 bssid = apdev[0]['bssid']
948 params = hs20_ap_params()
949 params['nai_realm'] = [ "0,example.com,21[5:6]" ]
950 hostapd.add_ap(apdev[0], params)
951
952 dev[0].hs20_enable()
953 dev[0].add_cred_values({ 'realm': "example.com",
954 'username': "certificate-user",
955 'ca_cert': "auth_serv/ca.pem",
956 'client_cert': "auth_serv/user.pem",
957 'private_key': "auth_serv/user.key"})
958 interworking_select(dev[0], None, no_match=True, freq="2412")
959
960 @remote_compatible
961 def test_ap_hs20_eap_invalid_cred(dev, apdev):
962 """Hotspot 2.0 connection with invalid cred configuration"""
963 bssid = apdev[0]['bssid']
964 params = hs20_ap_params()
965 hostapd.add_ap(apdev[0], params)
966
967 dev[0].hs20_enable()
968 dev[0].add_cred_values({ 'realm': "example.com",
969 'username': "certificate-user",
970 'client_cert': "auth_serv/user.pem" })
971 interworking_select(dev[0], None, no_match=True, freq="2412")
972
973 def test_ap_hs20_nai_realms(dev, apdev):
974 """Hotspot 2.0 connection and multiple NAI realms and TTLS/PAP"""
975 bssid = apdev[0]['bssid']
976 params = hs20_ap_params()
977 params['hessid'] = bssid
978 params['nai_realm'] = [ "0,no.match.here;example.com;no.match.here.either,21[2:1][5:7]" ]
979 hostapd.add_ap(apdev[0], params)
980
981 dev[0].hs20_enable()
982 id = dev[0].add_cred_values({ 'realm': "example.com",
983 'ca_cert': "auth_serv/ca.pem",
984 'username': "pap user",
985 'password': "password",
986 'domain': "example.com" })
987 interworking_select(dev[0], bssid, "home", freq="2412")
988 interworking_connect(dev[0], bssid, "TTLS")
989 check_sp_type(dev[0], "home")
990
991 def test_ap_hs20_roaming_consortium(dev, apdev):
992 """Hotspot 2.0 connection based on roaming consortium match"""
993 bssid = apdev[0]['bssid']
994 params = hs20_ap_params()
995 params['hessid'] = bssid
996 hostapd.add_ap(apdev[0], params)
997
998 dev[0].hs20_enable()
999 for consortium in [ "112233", "1020304050", "010203040506", "fedcba" ]:
1000 id = dev[0].add_cred_values({ 'username': "user",
1001 'password': "password",
1002 'domain': "example.com",
1003 'ca_cert': "auth_serv/ca.pem",
1004 'roaming_consortium': consortium,
1005 'eap': "PEAP" })
1006 interworking_select(dev[0], bssid, "home", freq="2412")
1007 interworking_connect(dev[0], bssid, "PEAP")
1008 check_sp_type(dev[0], "home")
1009 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1010 ev = dev[0].wait_event(["INTERWORKING-ALREADY-CONNECTED"], timeout=15)
1011 if ev is None:
1012 raise Exception("Timeout on already-connected event")
1013 dev[0].remove_cred(id)
1014
1015 def test_ap_hs20_roaming_consortiums_match(dev, apdev):
1016 """Hotspot 2.0 connection based on roaming_consortiums match"""
1017 bssid = apdev[0]['bssid']
1018 params = hs20_ap_params()
1019 params['hessid'] = bssid
1020 hostapd.add_ap(apdev[0], params)
1021
1022 dev[0].hs20_enable()
1023 tests = [ ("112233", "112233"),
1024 ("ffffff,1020304050,eeeeee", "1020304050") ]
1025 for consortium,selected in tests:
1026 id = dev[0].add_cred_values({ 'username': "user",
1027 'password': "password",
1028 'domain': "my.home.example.com",
1029 'ca_cert': "auth_serv/ca.pem",
1030 'roaming_consortiums': consortium,
1031 'eap': "PEAP" })
1032 interworking_select(dev[0], bssid, "roaming", freq="2412")
1033 interworking_connect(dev[0], bssid, "PEAP")
1034 check_sp_type(dev[0], "roaming")
1035 network_id = dev[0].get_status_field("id")
1036 sel = dev[0].get_network(network_id, "roaming_consortium_selection")
1037 if sel != selected:
1038 raise Exception("Unexpected roaming_consortium_selection value: " +
1039 sel)
1040 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1041 ev = dev[0].wait_event(["INTERWORKING-ALREADY-CONNECTED"], timeout=15)
1042 if ev is None:
1043 raise Exception("Timeout on already-connected event")
1044 dev[0].remove_cred(id)
1045
1046 def test_ap_hs20_max_roaming_consortiums(dev, apdev):
1047 """Maximum number of cred roaming_consortiums"""
1048 id = dev[0].add_cred()
1049 consortium = (36*",ffffff")[1:]
1050 if "OK" not in dev[0].request('SET_CRED %d roaming_consortiums "%s"' % (id, consortium)):
1051 raise Exception("Maximum number of consortium OIs rejected")
1052 consortium = (37*",ffffff")[1:]
1053 if "FAIL" not in dev[0].request('SET_CRED %d roaming_consortiums "%s"' % (id, consortium)):
1054 raise Exception("Over maximum number of consortium OIs accepted")
1055 dev[0].remove_cred(id)
1056
1057 def test_ap_hs20_roaming_consortium_invalid(dev, apdev):
1058 """Hotspot 2.0 connection and invalid roaming consortium ANQP-element"""
1059 bssid = apdev[0]['bssid']
1060 params = hs20_ap_params()
1061 params['hessid'] = bssid
1062 # Override Roaming Consortium ANQP-element with an incorrectly encoded
1063 # value.
1064 params['anqp_elem'] = "261:04fedcba"
1065 hostapd.add_ap(apdev[0], params)
1066
1067 dev[0].hs20_enable()
1068 id = dev[0].add_cred_values({ 'username': "user",
1069 'password': "password",
1070 'domain': "example.com",
1071 'ca_cert': "auth_serv/ca.pem",
1072 'roaming_consortium': "fedcba",
1073 'eap': "PEAP" })
1074 interworking_select(dev[0], bssid, "home", freq="2412", no_match=True)
1075
1076 def test_ap_hs20_roaming_consortium_element(dev, apdev):
1077 """Hotspot 2.0 connection and invalid roaming consortium element"""
1078 bssid = apdev[0]['bssid']
1079 params = hs20_ap_params()
1080 params['hessid'] = bssid
1081 del params['roaming_consortium']
1082 params['vendor_elements'] = '6f00'
1083 hapd = hostapd.add_ap(apdev[0], params)
1084
1085 dev[0].hs20_enable()
1086 dev[0].scan_for_bss(bssid, freq="2412")
1087 id = dev[0].add_cred_values({ 'username': "user",
1088 'password': "password",
1089 'domain': "example.com",
1090 'ca_cert': "auth_serv/ca.pem",
1091 'roaming_consortium': "112233",
1092 'eap': "PEAP" })
1093 interworking_select(dev[0], bssid, freq="2412", no_match=True)
1094
1095 hapd.set('vendor_elements', '6f020001')
1096 if "OK" not in hapd.request("UPDATE_BEACON"):
1097 raise Exception("UPDATE_BEACON failed")
1098 dev[0].request("BSS_FLUSH 0")
1099 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
1100 interworking_select(dev[0], bssid, freq="2412", no_match=True)
1101
1102 def test_ap_hs20_roaming_consortium_constraints(dev, apdev):
1103 """Hotspot 2.0 connection and roaming consortium constraints"""
1104 bssid = apdev[0]['bssid']
1105 params = hs20_ap_params()
1106 params['hessid'] = bssid
1107 params['bss_load_test'] = "12:200:20000"
1108 hostapd.add_ap(apdev[0], params)
1109
1110 dev[0].hs20_enable()
1111
1112 vals = { 'username': "user",
1113 'password': "password",
1114 'domain': "example.com",
1115 'ca_cert': "auth_serv/ca.pem",
1116 'roaming_consortium': "fedcba",
1117 'eap': "TTLS" }
1118 vals2 = vals.copy()
1119 vals2['required_roaming_consortium'] = "223344"
1120 id = dev[0].add_cred_values(vals2)
1121 interworking_select(dev[0], bssid, "home", freq="2412", no_match=True)
1122 dev[0].remove_cred(id)
1123
1124 vals2 = vals.copy()
1125 vals2['min_dl_bandwidth_home'] = "65500"
1126 id = dev[0].add_cred_values(vals2)
1127 dev[0].request("INTERWORKING_SELECT freq=2412")
1128 ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
1129 if ev is None:
1130 raise Exception("No AP found")
1131 if "below_min_backhaul=1" not in ev:
1132 raise Exception("below_min_backhaul not reported")
1133 dev[0].remove_cred(id)
1134
1135 vals2 = vals.copy()
1136 vals2['max_bss_load'] = "100"
1137 id = dev[0].add_cred_values(vals2)
1138 dev[0].request("INTERWORKING_SELECT freq=2412")
1139 ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
1140 if ev is None:
1141 raise Exception("No AP found")
1142 if "over_max_bss_load=1" not in ev:
1143 raise Exception("over_max_bss_load not reported")
1144 dev[0].remove_cred(id)
1145
1146 vals2 = vals.copy()
1147 vals2['req_conn_capab'] = "6:1234"
1148 vals2['domain'] = 'example.org'
1149 id = dev[0].add_cred_values(vals2)
1150
1151 dev[0].request("INTERWORKING_SELECT freq=2412")
1152 ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
1153 if ev is None:
1154 raise Exception("No AP found")
1155 if "conn_capab_missing=1" not in ev:
1156 raise Exception("conn_capab_missing not reported")
1157 dev[0].remove_cred(id)
1158
1159 values = default_cred()
1160 values['roaming_consortium'] = "fedcba"
1161 id3 = dev[0].add_cred_values(values)
1162
1163 vals2 = vals.copy()
1164 vals2['roaming_consortium'] = "fedcba"
1165 vals2['priority'] = "2"
1166 id = dev[0].add_cred_values(vals2)
1167
1168 values = default_cred()
1169 values['roaming_consortium'] = "fedcba"
1170 id2 = dev[0].add_cred_values(values)
1171
1172 dev[0].request("INTERWORKING_SELECT freq=2412")
1173 ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
1174 if ev is None:
1175 raise Exception("No AP found")
1176 dev[0].remove_cred(id)
1177 dev[0].remove_cred(id2)
1178 dev[0].remove_cred(id3)
1179
1180 def test_ap_hs20_3gpp_constraints(dev, apdev):
1181 """Hotspot 2.0 connection and 3GPP credential constraints"""
1182 bssid = apdev[0]['bssid']
1183 params = hs20_ap_params()
1184 params['hessid'] = bssid
1185 params['anqp_3gpp_cell_net'] = "555,444"
1186 params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org"
1187 params['bss_load_test'] = "12:200:20000"
1188 hapd = hostapd.add_ap(apdev[0], params)
1189
1190 dev[0].hs20_enable()
1191
1192 vals = { 'imsi': "555444-333222111",
1193 'eap': "SIM",
1194 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123" }
1195 vals2 = vals.copy()
1196 vals2['required_roaming_consortium'] = "223344"
1197 id = dev[0].add_cred_values(vals2)
1198 interworking_select(dev[0], bssid, "home", freq="2412", no_match=True)
1199 dev[0].remove_cred(id)
1200
1201 vals2 = vals.copy()
1202 vals2['min_dl_bandwidth_home'] = "65500"
1203 id = dev[0].add_cred_values(vals2)
1204 dev[0].request("INTERWORKING_SELECT freq=2412")
1205 ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
1206 if ev is None:
1207 raise Exception("No AP found")
1208 if "below_min_backhaul=1" not in ev:
1209 raise Exception("below_min_backhaul not reported")
1210 dev[0].remove_cred(id)
1211
1212 vals2 = vals.copy()
1213 vals2['max_bss_load'] = "100"
1214 id = dev[0].add_cred_values(vals2)
1215 dev[0].request("INTERWORKING_SELECT freq=2412")
1216 ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
1217 if ev is None:
1218 raise Exception("No AP found")
1219 if "over_max_bss_load=1" not in ev:
1220 raise Exception("over_max_bss_load not reported")
1221 dev[0].remove_cred(id)
1222
1223 values = default_cred()
1224 values['roaming_consortium'] = "fedcba"
1225 id3 = dev[0].add_cred_values(values)
1226
1227 vals2 = vals.copy()
1228 vals2['roaming_consortium'] = "fedcba"
1229 vals2['priority'] = "2"
1230 id = dev[0].add_cred_values(vals2)
1231
1232 values = default_cred()
1233 values['roaming_consortium'] = "fedcba"
1234 id2 = dev[0].add_cred_values(values)
1235
1236 dev[0].request("INTERWORKING_SELECT freq=2412")
1237 ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
1238 if ev is None:
1239 raise Exception("No AP found")
1240 dev[0].remove_cred(id)
1241 dev[0].remove_cred(id2)
1242 dev[0].remove_cred(id3)
1243
1244 hapd.disable()
1245 params = hs20_ap_params()
1246 params['hessid'] = bssid
1247 params['anqp_3gpp_cell_net'] = "555,444"
1248 params['bss_load_test'] = "12:200:20000"
1249 hapd = hostapd.add_ap(apdev[0], params)
1250 vals2 = vals.copy()
1251 vals2['req_conn_capab'] = "6:1234"
1252 id = dev[0].add_cred_values(vals2)
1253 dev[0].request("INTERWORKING_SELECT freq=2412")
1254 ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
1255 if ev is None:
1256 raise Exception("No AP found")
1257 if "conn_capab_missing=1" not in ev:
1258 raise Exception("conn_capab_missing not reported")
1259 dev[0].remove_cred(id)
1260
1261 def test_ap_hs20_connect_no_full_match(dev, apdev):
1262 """Hotspot 2.0 connection and no full match"""
1263 bssid = apdev[0]['bssid']
1264 params = hs20_ap_params()
1265 params['hessid'] = bssid
1266 params['anqp_3gpp_cell_net'] = "555,444"
1267 hostapd.add_ap(apdev[0], params)
1268
1269 dev[0].hs20_enable()
1270
1271 vals = { 'username': "user",
1272 'password': "password",
1273 'domain': "example.com",
1274 'ca_cert': "auth_serv/ca.pem",
1275 'roaming_consortium': "fedcba",
1276 'eap': "TTLS",
1277 'min_dl_bandwidth_home': "65500" }
1278 id = dev[0].add_cred_values(vals)
1279 dev[0].request("INTERWORKING_SELECT freq=2412")
1280 ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
1281 if ev is None:
1282 raise Exception("No AP found")
1283 if "below_min_backhaul=1" not in ev:
1284 raise Exception("below_min_backhaul not reported")
1285 interworking_connect(dev[0], bssid, "TTLS")
1286 dev[0].remove_cred(id)
1287 dev[0].wait_disconnected()
1288
1289 vals = { 'imsi': "555444-333222111", 'eap': "SIM",
1290 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123",
1291 'min_dl_bandwidth_roaming': "65500" }
1292 id = dev[0].add_cred_values(vals)
1293 dev[0].request("INTERWORKING_SELECT freq=2412")
1294 ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
1295 if ev is None:
1296 raise Exception("No AP found")
1297 if "below_min_backhaul=1" not in ev:
1298 raise Exception("below_min_backhaul not reported")
1299 interworking_connect(dev[0], bssid, "SIM")
1300 dev[0].remove_cred(id)
1301 dev[0].wait_disconnected()
1302
1303 def test_ap_hs20_username_roaming(dev, apdev):
1304 """Hotspot 2.0 connection in username/password credential (roaming)"""
1305 check_eap_capa(dev[0], "MSCHAPV2")
1306 bssid = apdev[0]['bssid']
1307 params = hs20_ap_params()
1308 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]",
1309 "0,roaming.example.com,21[2:4][5:7]",
1310 "0,another.example.com" ]
1311 params['domain_name'] = "another.example.com"
1312 params['hessid'] = bssid
1313 hostapd.add_ap(apdev[0], params)
1314
1315 dev[0].hs20_enable()
1316 id = dev[0].add_cred_values({ 'realm': "roaming.example.com",
1317 'username': "hs20-test",
1318 'password': "password",
1319 'ca_cert': "auth_serv/ca.pem",
1320 'domain': "example.com" })
1321 interworking_select(dev[0], bssid, "roaming", freq="2412")
1322 interworking_connect(dev[0], bssid, "TTLS")
1323 check_sp_type(dev[0], "roaming")
1324
1325 def test_ap_hs20_username_unknown(dev, apdev):
1326 """Hotspot 2.0 connection in username/password credential (no domain in cred)"""
1327 check_eap_capa(dev[0], "MSCHAPV2")
1328 bssid = apdev[0]['bssid']
1329 params = hs20_ap_params()
1330 params['hessid'] = bssid
1331 hostapd.add_ap(apdev[0], params)
1332
1333 dev[0].hs20_enable()
1334 id = dev[0].add_cred_values({ 'realm': "example.com",
1335 'ca_cert': "auth_serv/ca.pem",
1336 'username': "hs20-test",
1337 'password': "password" })
1338 interworking_select(dev[0], bssid, "unknown", freq="2412")
1339 interworking_connect(dev[0], bssid, "TTLS")
1340 check_sp_type(dev[0], "unknown")
1341
1342 def test_ap_hs20_username_unknown2(dev, apdev):
1343 """Hotspot 2.0 connection in username/password credential (no domain advertized)"""
1344 check_eap_capa(dev[0], "MSCHAPV2")
1345 bssid = apdev[0]['bssid']
1346 params = hs20_ap_params()
1347 params['hessid'] = bssid
1348 del params['domain_name']
1349 hostapd.add_ap(apdev[0], params)
1350
1351 dev[0].hs20_enable()
1352 id = dev[0].add_cred_values({ 'realm': "example.com",
1353 'ca_cert': "auth_serv/ca.pem",
1354 'username': "hs20-test",
1355 'password': "password",
1356 'domain': "example.com" })
1357 interworking_select(dev[0], bssid, "unknown", freq="2412")
1358 interworking_connect(dev[0], bssid, "TTLS")
1359 check_sp_type(dev[0], "unknown")
1360
1361 def test_ap_hs20_gas_while_associated(dev, apdev):
1362 """Hotspot 2.0 connection with GAS query while associated"""
1363 check_eap_capa(dev[0], "MSCHAPV2")
1364 bssid = apdev[0]['bssid']
1365 params = hs20_ap_params()
1366 params['hessid'] = bssid
1367 hostapd.add_ap(apdev[0], params)
1368
1369 dev[0].hs20_enable()
1370 id = dev[0].add_cred_values({ 'realm': "example.com",
1371 'ca_cert': "auth_serv/ca.pem",
1372 'username': "hs20-test",
1373 'password': "password",
1374 'domain': "example.com" })
1375 interworking_select(dev[0], bssid, "home", freq="2412")
1376 interworking_connect(dev[0], bssid, "TTLS")
1377
1378 logger.info("Verifying GAS query while associated")
1379 dev[0].request("FETCH_ANQP")
1380 for i in range(0, 6):
1381 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
1382 if ev is None:
1383 raise Exception("Operation timed out")
1384
1385 def test_ap_hs20_gas_with_another_ap_while_associated(dev, apdev):
1386 """GAS query with another AP while associated"""
1387 check_eap_capa(dev[0], "MSCHAPV2")
1388 bssid = apdev[0]['bssid']
1389 params = hs20_ap_params()
1390 params['hessid'] = bssid
1391 hostapd.add_ap(apdev[0], params)
1392
1393 bssid2 = apdev[1]['bssid']
1394 params = hs20_ap_params()
1395 params['hessid'] = bssid2
1396 params['nai_realm'] = [ "0,no-match.example.org,13[5:6],21[2:4][5:7]" ]
1397 hostapd.add_ap(apdev[1], params)
1398
1399 dev[0].hs20_enable()
1400 id = dev[0].add_cred_values({ 'realm': "example.com",
1401 'ca_cert': "auth_serv/ca.pem",
1402 'username': "hs20-test",
1403 'password': "password",
1404 'domain': "example.com" })
1405 interworking_select(dev[0], bssid, "home", freq="2412")
1406 interworking_connect(dev[0], bssid, "TTLS")
1407 dev[0].dump_monitor()
1408
1409 logger.info("Verifying GAS query with same AP while associated")
1410 dev[0].request("ANQP_GET " + bssid + " 263")
1411 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
1412 if ev is None:
1413 raise Exception("ANQP operation timed out")
1414 dev[0].dump_monitor()
1415
1416 logger.info("Verifying GAS query with another AP while associated")
1417 dev[0].scan_for_bss(bssid2, 2412)
1418 dev[0].request("ANQP_GET " + bssid2 + " 263")
1419 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
1420 if ev is None:
1421 raise Exception("ANQP operation timed out")
1422
1423 def test_ap_hs20_gas_while_associated_with_pmf(dev, apdev):
1424 """Hotspot 2.0 connection with GAS query while associated and using PMF"""
1425 check_eap_capa(dev[0], "MSCHAPV2")
1426 try:
1427 _test_ap_hs20_gas_while_associated_with_pmf(dev, apdev)
1428 finally:
1429 dev[0].request("SET pmf 0")
1430
1431 def _test_ap_hs20_gas_while_associated_with_pmf(dev, apdev):
1432 bssid = apdev[0]['bssid']
1433 params = hs20_ap_params()
1434 params['hessid'] = bssid
1435 hostapd.add_ap(apdev[0], params)
1436
1437 bssid2 = apdev[1]['bssid']
1438 params = hs20_ap_params()
1439 params['hessid'] = bssid2
1440 params['nai_realm'] = [ "0,no-match.example.org,13[5:6],21[2:4][5:7]" ]
1441 hostapd.add_ap(apdev[1], params)
1442
1443 dev[0].hs20_enable()
1444 dev[0].request("SET pmf 2")
1445 id = dev[0].add_cred_values({ 'realm': "example.com",
1446 'ca_cert': "auth_serv/ca.pem",
1447 'username': "hs20-test",
1448 'password': "password",
1449 'domain': "example.com" })
1450 interworking_select(dev[0], bssid, "home", freq="2412")
1451 interworking_connect(dev[0], bssid, "TTLS")
1452
1453 logger.info("Verifying GAS query while associated")
1454 dev[0].request("FETCH_ANQP")
1455 for i in range(0, 2 * 6):
1456 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
1457 if ev is None:
1458 raise Exception("Operation timed out")
1459
1460 def test_ap_hs20_gas_with_another_ap_while_using_pmf(dev, apdev):
1461 """GAS query with another AP while associated and using PMF"""
1462 check_eap_capa(dev[0], "MSCHAPV2")
1463 try:
1464 _test_ap_hs20_gas_with_another_ap_while_using_pmf(dev, apdev)
1465 finally:
1466 dev[0].request("SET pmf 0")
1467
1468 def _test_ap_hs20_gas_with_another_ap_while_using_pmf(dev, apdev):
1469 bssid = apdev[0]['bssid']
1470 params = hs20_ap_params()
1471 params['hessid'] = bssid
1472 hostapd.add_ap(apdev[0], params)
1473
1474 bssid2 = apdev[1]['bssid']
1475 params = hs20_ap_params()
1476 params['hessid'] = bssid2
1477 params['nai_realm'] = [ "0,no-match.example.org,13[5:6],21[2:4][5:7]" ]
1478 hostapd.add_ap(apdev[1], params)
1479
1480 dev[0].hs20_enable()
1481 dev[0].request("SET pmf 2")
1482 id = dev[0].add_cred_values({ 'realm': "example.com",
1483 'ca_cert': "auth_serv/ca.pem",
1484 'username': "hs20-test",
1485 'password': "password",
1486 'domain': "example.com" })
1487 interworking_select(dev[0], bssid, "home", freq="2412")
1488 interworking_connect(dev[0], bssid, "TTLS")
1489 dev[0].dump_monitor()
1490
1491 logger.info("Verifying GAS query with same AP while associated")
1492 dev[0].request("ANQP_GET " + bssid + " 263")
1493 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
1494 if ev is None:
1495 raise Exception("ANQP operation timed out")
1496 dev[0].dump_monitor()
1497
1498 logger.info("Verifying GAS query with another AP while associated")
1499 dev[0].scan_for_bss(bssid2, 2412)
1500 dev[0].request("ANQP_GET " + bssid2 + " 263")
1501 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
1502 if ev is None:
1503 raise Exception("ANQP operation timed out")
1504
1505 def test_ap_hs20_gas_frag_while_associated(dev, apdev):
1506 """Hotspot 2.0 connection with fragmented GAS query while associated"""
1507 check_eap_capa(dev[0], "MSCHAPV2")
1508 bssid = apdev[0]['bssid']
1509 params = hs20_ap_params()
1510 params['hessid'] = bssid
1511 hapd = hostapd.add_ap(apdev[0], params)
1512 hapd.set("gas_frag_limit", "50")
1513
1514 dev[0].hs20_enable()
1515 id = dev[0].add_cred_values({ 'realm': "example.com",
1516 'ca_cert': "auth_serv/ca.pem",
1517 'username': "hs20-test",
1518 'password': "password",
1519 'domain': "example.com" })
1520 interworking_select(dev[0], bssid, "home", freq="2412")
1521 interworking_connect(dev[0], bssid, "TTLS")
1522
1523 logger.info("Verifying GAS query while associated")
1524 dev[0].request("FETCH_ANQP")
1525 for i in range(0, 6):
1526 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
1527 if ev is None:
1528 raise Exception("Operation timed out")
1529
1530 def test_ap_hs20_multiple_connects(dev, apdev):
1531 """Hotspot 2.0 connection through multiple network selections"""
1532 check_eap_capa(dev[0], "MSCHAPV2")
1533 bssid = apdev[0]['bssid']
1534 params = hs20_ap_params()
1535 params['hessid'] = bssid
1536 hostapd.add_ap(apdev[0], params)
1537
1538 dev[0].hs20_enable()
1539 values = { 'realm': "example.com",
1540 'ca_cert': "auth_serv/ca.pem",
1541 'username': "hs20-test",
1542 'password': "password",
1543 'domain': "example.com" }
1544 id = dev[0].add_cred_values(values)
1545
1546 dev[0].scan_for_bss(bssid, freq="2412")
1547
1548 for i in range(0, 3):
1549 logger.info("Starting Interworking network selection")
1550 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1551 while True:
1552 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH",
1553 "INTERWORKING-ALREADY-CONNECTED",
1554 "CTRL-EVENT-CONNECTED"], timeout=15)
1555 if ev is None:
1556 raise Exception("Connection timed out")
1557 if "INTERWORKING-NO-MATCH" in ev:
1558 raise Exception("Matching AP not found")
1559 if "CTRL-EVENT-CONNECTED" in ev:
1560 break
1561 if i == 2 and "INTERWORKING-ALREADY-CONNECTED" in ev:
1562 break
1563 if i == 0:
1564 dev[0].request("DISCONNECT")
1565 dev[0].dump_monitor()
1566
1567 networks = dev[0].list_networks()
1568 if len(networks) > 1:
1569 raise Exception("Duplicated network block detected")
1570
1571 def test_ap_hs20_disallow_aps(dev, apdev):
1572 """Hotspot 2.0 connection and disallow_aps"""
1573 bssid = apdev[0]['bssid']
1574 params = hs20_ap_params()
1575 params['hessid'] = bssid
1576 hostapd.add_ap(apdev[0], params)
1577
1578 dev[0].hs20_enable()
1579 values = { 'realm': "example.com",
1580 'ca_cert': "auth_serv/ca.pem",
1581 'username': "hs20-test",
1582 'password': "password",
1583 'domain': "example.com" }
1584 id = dev[0].add_cred_values(values)
1585
1586 dev[0].scan_for_bss(bssid, freq="2412")
1587
1588 logger.info("Verify disallow_aps bssid")
1589 dev[0].request("SET disallow_aps bssid " + bssid.translate(None, ':'))
1590 dev[0].request("INTERWORKING_SELECT auto")
1591 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=15)
1592 if ev is None:
1593 raise Exception("Network selection timed out")
1594 dev[0].dump_monitor()
1595
1596 logger.info("Verify disallow_aps ssid")
1597 dev[0].request("SET disallow_aps ssid 746573742d68733230")
1598 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1599 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=15)
1600 if ev is None:
1601 raise Exception("Network selection timed out")
1602 dev[0].dump_monitor()
1603
1604 logger.info("Verify disallow_aps clear")
1605 dev[0].request("SET disallow_aps ")
1606 interworking_select(dev[0], bssid, "home", freq="2412")
1607
1608 dev[0].request("SET disallow_aps bssid " + bssid.translate(None, ':'))
1609 ret = dev[0].request("INTERWORKING_CONNECT " + bssid)
1610 if "FAIL" not in ret:
1611 raise Exception("INTERWORKING_CONNECT to disallowed BSS not rejected")
1612
1613 if "FAIL" not in dev[0].request("INTERWORKING_CONNECT foo"):
1614 raise Exception("Invalid INTERWORKING_CONNECT not rejected")
1615 if "FAIL" not in dev[0].request("INTERWORKING_CONNECT 00:11:22:33:44:55"):
1616 raise Exception("Invalid INTERWORKING_CONNECT not rejected")
1617
1618 def policy_test(dev, ap, values, only_one=True):
1619 dev.dump_monitor()
1620 if ap:
1621 logger.info("Verify network selection to AP " + ap['ifname'])
1622 bssid = ap['bssid']
1623 dev.scan_for_bss(bssid, freq="2412")
1624 else:
1625 logger.info("Verify network selection")
1626 bssid = None
1627 dev.hs20_enable()
1628 id = dev.add_cred_values(values)
1629 dev.request("INTERWORKING_SELECT auto freq=2412")
1630 events = []
1631 while True:
1632 ev = dev.wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH",
1633 "INTERWORKING-BLACKLISTED",
1634 "INTERWORKING-SELECTED"], timeout=15)
1635 if ev is None:
1636 raise Exception("Network selection timed out")
1637 events.append(ev)
1638 if "INTERWORKING-NO-MATCH" in ev:
1639 raise Exception("Matching AP not found")
1640 if bssid and only_one and "INTERWORKING-AP" in ev and bssid not in ev:
1641 raise Exception("Unexpected AP claimed acceptable")
1642 if "INTERWORKING-SELECTED" in ev:
1643 if bssid and bssid not in ev:
1644 raise Exception("Selected incorrect BSS")
1645 break
1646
1647 ev = dev.wait_connected(timeout=15)
1648 if bssid and bssid not in ev:
1649 raise Exception("Connected to incorrect BSS")
1650
1651 conn_bssid = dev.get_status_field("bssid")
1652 if bssid and conn_bssid != bssid:
1653 raise Exception("bssid information points to incorrect BSS")
1654
1655 dev.remove_cred(id)
1656 dev.dump_monitor()
1657 return events
1658
1659 def default_cred(domain=None, user="hs20-test"):
1660 cred = { 'realm': "example.com",
1661 'ca_cert': "auth_serv/ca.pem",
1662 'username': user,
1663 'password': "password" }
1664 if domain:
1665 cred['domain'] = domain
1666 return cred
1667
1668 def test_ap_hs20_prefer_home(dev, apdev):
1669 """Hotspot 2.0 required roaming consortium"""
1670 check_eap_capa(dev[0], "MSCHAPV2")
1671 params = hs20_ap_params()
1672 params['domain_name'] = "example.org"
1673 hostapd.add_ap(apdev[0], params)
1674
1675 params = hs20_ap_params()
1676 params['ssid'] = "test-hs20-other"
1677 params['domain_name'] = "example.com"
1678 hostapd.add_ap(apdev[1], params)
1679
1680 values = default_cred()
1681 values['domain'] = "example.com"
1682 policy_test(dev[0], apdev[1], values, only_one=False)
1683 values['domain'] = "example.org"
1684 policy_test(dev[0], apdev[0], values, only_one=False)
1685
1686 def test_ap_hs20_req_roaming_consortium(dev, apdev):
1687 """Hotspot 2.0 required roaming consortium"""
1688 check_eap_capa(dev[0], "MSCHAPV2")
1689 params = hs20_ap_params()
1690 hostapd.add_ap(apdev[0], params)
1691
1692 params = hs20_ap_params()
1693 params['ssid'] = "test-hs20-other"
1694 params['roaming_consortium'] = [ "223344" ]
1695 hostapd.add_ap(apdev[1], params)
1696
1697 values = default_cred()
1698 values['required_roaming_consortium'] = "223344"
1699 policy_test(dev[0], apdev[1], values)
1700 values['required_roaming_consortium'] = "112233"
1701 policy_test(dev[0], apdev[0], values)
1702
1703 id = dev[0].add_cred()
1704 dev[0].set_cred(id, "required_roaming_consortium", "112233")
1705 dev[0].set_cred(id, "required_roaming_consortium", "112233445566778899aabbccddeeff")
1706
1707 for val in [ "", "1", "11", "1122", "1122334", "112233445566778899aabbccddeeff00" ]:
1708 if "FAIL" not in dev[0].request('SET_CRED {} required_roaming_consortium {}'.format(id, val)):
1709 raise Exception("Invalid roaming consortium value accepted: " + val)
1710
1711 def test_ap_hs20_req_roaming_consortium_no_match(dev, apdev):
1712 """Hotspot 2.0 required roaming consortium and no match"""
1713 check_eap_capa(dev[0], "MSCHAPV2")
1714 params = hs20_ap_params()
1715 del params['roaming_consortium']
1716 hostapd.add_ap(apdev[0], params)
1717
1718 params = hs20_ap_params()
1719 params['ssid'] = "test-hs20-other"
1720 params['roaming_consortium'] = [ "223345" ]
1721 hostapd.add_ap(apdev[1], params)
1722
1723 values = default_cred()
1724 values['required_roaming_consortium'] = "223344"
1725 dev[0].hs20_enable()
1726 id = dev[0].add_cred_values(values)
1727 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1728 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=10)
1729 if ev is None:
1730 raise Exception("INTERWORKING-NO-MATCH not reported")
1731
1732 def test_ap_hs20_excluded_ssid(dev, apdev):
1733 """Hotspot 2.0 exclusion based on SSID"""
1734 check_eap_capa(dev[0], "MSCHAPV2")
1735 params = hs20_ap_params()
1736 params['roaming_consortium'] = [ "223344" ]
1737 params['anqp_3gpp_cell_net'] = "555,444"
1738 hostapd.add_ap(apdev[0], params)
1739
1740 params = hs20_ap_params()
1741 params['ssid'] = "test-hs20-other"
1742 params['roaming_consortium'] = [ "223344" ]
1743 params['anqp_3gpp_cell_net'] = "555,444"
1744 hostapd.add_ap(apdev[1], params)
1745
1746 values = default_cred()
1747 values['excluded_ssid'] = "test-hs20"
1748 events = policy_test(dev[0], apdev[1], values)
1749 ev = [e for e in events if "INTERWORKING-BLACKLISTED " + apdev[0]['bssid'] in e]
1750 if len(ev) != 1:
1751 raise Exception("Excluded network not reported")
1752 values['excluded_ssid'] = "test-hs20-other"
1753 events = policy_test(dev[0], apdev[0], values)
1754 ev = [e for e in events if "INTERWORKING-BLACKLISTED " + apdev[1]['bssid'] in e]
1755 if len(ev) != 1:
1756 raise Exception("Excluded network not reported")
1757
1758 values = default_cred()
1759 values['roaming_consortium'] = "223344"
1760 values['eap'] = "TTLS"
1761 values['phase2'] = "auth=MSCHAPV2"
1762 values['excluded_ssid'] = "test-hs20"
1763 events = policy_test(dev[0], apdev[1], values)
1764 ev = [e for e in events if "INTERWORKING-BLACKLISTED " + apdev[0]['bssid'] in e]
1765 if len(ev) != 1:
1766 raise Exception("Excluded network not reported")
1767
1768 values = { 'imsi': "555444-333222111", 'eap': "SIM",
1769 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123",
1770 'excluded_ssid': "test-hs20" }
1771 events = policy_test(dev[0], apdev[1], values)
1772 ev = [e for e in events if "INTERWORKING-BLACKLISTED " + apdev[0]['bssid'] in e]
1773 if len(ev) != 1:
1774 raise Exception("Excluded network not reported")
1775
1776 def test_ap_hs20_roam_to_higher_prio(dev, apdev):
1777 """Hotspot 2.0 and roaming from current to higher priority network"""
1778 check_eap_capa(dev[0], "MSCHAPV2")
1779 bssid = apdev[0]['bssid']
1780 params = hs20_ap_params(ssid="test-hs20-visited")
1781 params['domain_name'] = "visited.example.org"
1782 hostapd.add_ap(apdev[0], params)
1783
1784 dev[0].hs20_enable()
1785 id = dev[0].add_cred_values({ 'realm': "example.com",
1786 'ca_cert': "auth_serv/ca.pem",
1787 'username': "hs20-test",
1788 'password': "password",
1789 'domain': "example.com" })
1790 logger.info("Connect to the only network option")
1791 interworking_select(dev[0], bssid, "roaming", freq="2412")
1792 dev[0].dump_monitor()
1793 interworking_connect(dev[0], bssid, "TTLS")
1794
1795 logger.info("Start another AP (home operator) and reconnect")
1796 bssid2 = apdev[1]['bssid']
1797 params = hs20_ap_params(ssid="test-hs20-home")
1798 params['domain_name'] = "example.com"
1799 hostapd.add_ap(apdev[1], params)
1800
1801 dev[0].scan_for_bss(bssid2, freq="2412", force_scan=True)
1802 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1803 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH",
1804 "INTERWORKING-ALREADY-CONNECTED",
1805 "CTRL-EVENT-CONNECTED"], timeout=15)
1806 if ev is None:
1807 raise Exception("Connection timed out")
1808 if "INTERWORKING-NO-MATCH" in ev:
1809 raise Exception("Matching AP not found")
1810 if "INTERWORKING-ALREADY-CONNECTED" in ev:
1811 raise Exception("Unexpected AP selected")
1812 if bssid2 not in ev:
1813 raise Exception("Unexpected BSSID after reconnection")
1814
1815 def test_ap_hs20_domain_suffix_match_full(dev, apdev):
1816 """Hotspot 2.0 and domain_suffix_match"""
1817 check_domain_match_full(dev[0])
1818 check_eap_capa(dev[0], "MSCHAPV2")
1819 bssid = apdev[0]['bssid']
1820 params = hs20_ap_params()
1821 hostapd.add_ap(apdev[0], params)
1822
1823 dev[0].hs20_enable()
1824 id = dev[0].add_cred_values({ 'realm': "example.com",
1825 'username': "hs20-test",
1826 'password': "password",
1827 'ca_cert': "auth_serv/ca.pem",
1828 'domain': "example.com",
1829 'domain_suffix_match': "server.w1.fi" })
1830 interworking_select(dev[0], bssid, "home", freq="2412")
1831 dev[0].dump_monitor()
1832 interworking_connect(dev[0], bssid, "TTLS")
1833 dev[0].request("REMOVE_NETWORK all")
1834 dev[0].dump_monitor()
1835
1836 dev[0].set_cred_quoted(id, "domain_suffix_match", "no-match.example.com")
1837 interworking_select(dev[0], bssid, "home", freq="2412")
1838 dev[0].dump_monitor()
1839 dev[0].request("INTERWORKING_CONNECT " + bssid)
1840 ev = dev[0].wait_event(["CTRL-EVENT-EAP-TLS-CERT-ERROR"])
1841 if ev is None:
1842 raise Exception("TLS certificate error not reported")
1843 if "Domain suffix mismatch" not in ev:
1844 raise Exception("Domain suffix mismatch not reported")
1845
1846 def test_ap_hs20_domain_suffix_match(dev, apdev):
1847 """Hotspot 2.0 and domain_suffix_match"""
1848 check_eap_capa(dev[0], "MSCHAPV2")
1849 check_domain_match_full(dev[0])
1850 bssid = apdev[0]['bssid']
1851 params = hs20_ap_params()
1852 hostapd.add_ap(apdev[0], params)
1853
1854 dev[0].hs20_enable()
1855 id = dev[0].add_cred_values({ 'realm': "example.com",
1856 'username': "hs20-test",
1857 'password': "password",
1858 'ca_cert': "auth_serv/ca.pem",
1859 'domain': "example.com",
1860 'domain_suffix_match': "w1.fi" })
1861 interworking_select(dev[0], bssid, "home", freq="2412")
1862 dev[0].dump_monitor()
1863 interworking_connect(dev[0], bssid, "TTLS")
1864
1865 def test_ap_hs20_roaming_partner_preference(dev, apdev):
1866 """Hotspot 2.0 and roaming partner preference"""
1867 check_eap_capa(dev[0], "MSCHAPV2")
1868 params = hs20_ap_params()
1869 params['domain_name'] = "roaming.example.org"
1870 hostapd.add_ap(apdev[0], params)
1871
1872 params = hs20_ap_params()
1873 params['ssid'] = "test-hs20-other"
1874 params['domain_name'] = "roaming.example.net"
1875 hostapd.add_ap(apdev[1], params)
1876
1877 logger.info("Verify default vs. specified preference")
1878 values = default_cred()
1879 values['roaming_partner'] = "roaming.example.net,1,127,*"
1880 policy_test(dev[0], apdev[1], values, only_one=False)
1881 values['roaming_partner'] = "roaming.example.net,1,129,*"
1882 policy_test(dev[0], apdev[0], values, only_one=False)
1883
1884 logger.info("Verify partial FQDN match")
1885 values['roaming_partner'] = "example.net,0,0,*"
1886 policy_test(dev[0], apdev[1], values, only_one=False)
1887 values['roaming_partner'] = "example.net,0,255,*"
1888 policy_test(dev[0], apdev[0], values, only_one=False)
1889
1890 def test_ap_hs20_max_bss_load(dev, apdev):
1891 """Hotspot 2.0 and maximum BSS load"""
1892 check_eap_capa(dev[0], "MSCHAPV2")
1893 params = hs20_ap_params()
1894 params['bss_load_test'] = "12:200:20000"
1895 hostapd.add_ap(apdev[0], params)
1896
1897 params = hs20_ap_params()
1898 params['ssid'] = "test-hs20-other"
1899 params['bss_load_test'] = "5:20:10000"
1900 hostapd.add_ap(apdev[1], params)
1901
1902 logger.info("Verify maximum BSS load constraint")
1903 values = default_cred()
1904 values['domain'] = "example.com"
1905 values['max_bss_load'] = "100"
1906 events = policy_test(dev[0], apdev[1], values, only_one=False)
1907
1908 ev = [e for e in events if "INTERWORKING-AP " + apdev[0]['bssid'] in e]
1909 if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
1910 raise Exception("Maximum BSS Load case not noticed")
1911 ev = [e for e in events if "INTERWORKING-AP " + apdev[1]['bssid'] in e]
1912 if len(ev) != 1 or "over_max_bss_load=1" in ev[0]:
1913 raise Exception("Maximum BSS Load case reported incorrectly")
1914
1915 logger.info("Verify maximum BSS load does not prevent connection")
1916 values['max_bss_load'] = "1"
1917 events = policy_test(dev[0], None, values)
1918
1919 ev = [e for e in events if "INTERWORKING-AP " + apdev[0]['bssid'] in e]
1920 if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
1921 raise Exception("Maximum BSS Load case not noticed")
1922 ev = [e for e in events if "INTERWORKING-AP " + apdev[1]['bssid'] in e]
1923 if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
1924 raise Exception("Maximum BSS Load case not noticed")
1925
1926 def test_ap_hs20_max_bss_load2(dev, apdev):
1927 """Hotspot 2.0 and maximum BSS load with one AP not advertising"""
1928 check_eap_capa(dev[0], "MSCHAPV2")
1929 params = hs20_ap_params()
1930 params['bss_load_test'] = "12:200:20000"
1931 hostapd.add_ap(apdev[0], params)
1932
1933 params = hs20_ap_params()
1934 params['ssid'] = "test-hs20-other"
1935 hostapd.add_ap(apdev[1], params)
1936
1937 logger.info("Verify maximum BSS load constraint with AP advertisement")
1938 values = default_cred()
1939 values['domain'] = "example.com"
1940 values['max_bss_load'] = "100"
1941 events = policy_test(dev[0], apdev[1], values, only_one=False)
1942
1943 ev = [e for e in events if "INTERWORKING-AP " + apdev[0]['bssid'] in e]
1944 if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
1945 raise Exception("Maximum BSS Load case not noticed")
1946 ev = [e for e in events if "INTERWORKING-AP " + apdev[1]['bssid'] in e]
1947 if len(ev) != 1 or "over_max_bss_load=1" in ev[0]:
1948 raise Exception("Maximum BSS Load case reported incorrectly")
1949
1950 def test_ap_hs20_max_bss_load_roaming(dev, apdev):
1951 """Hotspot 2.0 and maximum BSS load (roaming)"""
1952 check_eap_capa(dev[0], "MSCHAPV2")
1953 params = hs20_ap_params()
1954 params['bss_load_test'] = "12:200:20000"
1955 hostapd.add_ap(apdev[0], params)
1956
1957 values = default_cred()
1958 values['domain'] = "roaming.example.com"
1959 values['max_bss_load'] = "100"
1960 events = policy_test(dev[0], apdev[0], values, only_one=True)
1961 ev = [e for e in events if "INTERWORKING-AP " + apdev[0]['bssid'] in e]
1962 if len(ev) != 1:
1963 raise Exception("No INTERWORKING-AP event")
1964 if "over_max_bss_load=1" in ev[0]:
1965 raise Exception("Maximum BSS Load reported for roaming")
1966
1967 def test_ap_hs20_multi_cred_sp_prio(dev, apdev):
1968 """Hotspot 2.0 multi-cred sp_priority"""
1969 check_eap_capa(dev[0], "MSCHAPV2")
1970 try:
1971 _test_ap_hs20_multi_cred_sp_prio(dev, apdev)
1972 finally:
1973 dev[0].request("SET external_sim 0")
1974
1975 def _test_ap_hs20_multi_cred_sp_prio(dev, apdev):
1976 hlr_auc_gw_available()
1977 bssid = apdev[0]['bssid']
1978 params = hs20_ap_params()
1979 params['hessid'] = bssid
1980 del params['domain_name']
1981 params['anqp_3gpp_cell_net'] = "232,01"
1982 hostapd.add_ap(apdev[0], params)
1983
1984 dev[0].hs20_enable()
1985 dev[0].scan_for_bss(bssid, freq="2412")
1986 dev[0].request("SET external_sim 1")
1987 id1 = dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM",
1988 'provisioning_sp': "example.com",
1989 'sp_priority' :"1" })
1990 id2 = dev[0].add_cred_values({ 'realm': "example.com",
1991 'ca_cert': "auth_serv/ca.pem",
1992 'username': "hs20-test",
1993 'password': "password",
1994 'domain': "example.com",
1995 'provisioning_sp': "example.com",
1996 'sp_priority': "2" })
1997 dev[0].dump_monitor()
1998 dev[0].scan_for_bss(bssid, freq="2412")
1999 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2000 interworking_ext_sim_auth(dev[0], "SIM")
2001 check_sp_type(dev[0], "unknown")
2002 dev[0].request("REMOVE_NETWORK all")
2003
2004 dev[0].set_cred(id1, "sp_priority", "2")
2005 dev[0].set_cred(id2, "sp_priority", "1")
2006 dev[0].dump_monitor()
2007 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2008 interworking_auth(dev[0], "TTLS")
2009 check_sp_type(dev[0], "unknown")
2010
2011 def test_ap_hs20_multi_cred_sp_prio2(dev, apdev):
2012 """Hotspot 2.0 multi-cred sp_priority with two BSSes"""
2013 check_eap_capa(dev[0], "MSCHAPV2")
2014 try:
2015 _test_ap_hs20_multi_cred_sp_prio2(dev, apdev)
2016 finally:
2017 dev[0].request("SET external_sim 0")
2018
2019 def _test_ap_hs20_multi_cred_sp_prio2(dev, apdev):
2020 hlr_auc_gw_available()
2021 bssid = apdev[0]['bssid']
2022 params = hs20_ap_params()
2023 params['hessid'] = bssid
2024 del params['nai_realm']
2025 del params['domain_name']
2026 params['anqp_3gpp_cell_net'] = "232,01"
2027 hostapd.add_ap(apdev[0], params)
2028
2029 bssid2 = apdev[1]['bssid']
2030 params = hs20_ap_params()
2031 params['ssid'] = "test-hs20-other"
2032 params['hessid'] = bssid2
2033 del params['domain_name']
2034 del params['anqp_3gpp_cell_net']
2035 hostapd.add_ap(apdev[1], params)
2036
2037 dev[0].hs20_enable()
2038 dev[0].request("SET external_sim 1")
2039 id1 = dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM",
2040 'provisioning_sp': "example.com",
2041 'sp_priority': "1" })
2042 id2 = dev[0].add_cred_values({ 'realm': "example.com",
2043 'ca_cert': "auth_serv/ca.pem",
2044 'username': "hs20-test",
2045 'password': "password",
2046 'domain': "example.com",
2047 'provisioning_sp': "example.com",
2048 'sp_priority': "2" })
2049 dev[0].dump_monitor()
2050 dev[0].scan_for_bss(bssid, freq="2412")
2051 dev[0].scan_for_bss(bssid2, freq="2412")
2052 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2053 interworking_ext_sim_auth(dev[0], "SIM")
2054 check_sp_type(dev[0], "unknown")
2055 conn_bssid = dev[0].get_status_field("bssid")
2056 if conn_bssid != bssid:
2057 raise Exception("Connected to incorrect BSS")
2058 dev[0].request("REMOVE_NETWORK all")
2059
2060 dev[0].set_cred(id1, "sp_priority", "2")
2061 dev[0].set_cred(id2, "sp_priority", "1")
2062 dev[0].dump_monitor()
2063 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2064 interworking_auth(dev[0], "TTLS")
2065 check_sp_type(dev[0], "unknown")
2066 conn_bssid = dev[0].get_status_field("bssid")
2067 if conn_bssid != bssid2:
2068 raise Exception("Connected to incorrect BSS")
2069
2070 def test_ap_hs20_multi_cred_sp_prio_same(dev, apdev):
2071 """Hotspot 2.0 multi-cred and same sp_priority"""
2072 check_eap_capa(dev[0], "MSCHAPV2")
2073 hlr_auc_gw_available()
2074 bssid = apdev[0]['bssid']
2075 params = hs20_ap_params()
2076 params['hessid'] = bssid
2077 del params['domain_name']
2078 params['anqp_3gpp_cell_net'] = "232,01"
2079 hostapd.add_ap(apdev[0], params)
2080
2081 dev[0].hs20_enable()
2082 dev[0].scan_for_bss(bssid, freq="2412")
2083 id1 = dev[0].add_cred_values({ 'realm': "example.com",
2084 'ca_cert': "auth_serv/ca.pem",
2085 'username': "hs20-test",
2086 'password': "password",
2087 'domain': "domain1.example.com",
2088 'provisioning_sp': "example.com",
2089 'sp_priority': "1" })
2090 id2 = dev[0].add_cred_values({ 'realm': "example.com",
2091 'ca_cert': "auth_serv/ca.pem",
2092 'username': "hs20-test",
2093 'password': "password",
2094 'domain': "domain2.example.com",
2095 'provisioning_sp': "example.com",
2096 'sp_priority': "1" })
2097 dev[0].dump_monitor()
2098 dev[0].scan_for_bss(bssid, freq="2412")
2099 check_auto_select(dev[0], bssid)
2100
2101 def check_conn_capab_selection(dev, type, missing):
2102 dev.request("INTERWORKING_SELECT freq=2412")
2103 ev = dev.wait_event(["INTERWORKING-AP"])
2104 if ev is None:
2105 raise Exception("Network selection timed out")
2106 if "type=" + type not in ev:
2107 raise Exception("Unexpected network type")
2108 if missing and "conn_capab_missing=1" not in ev:
2109 raise Exception("conn_capab_missing not reported")
2110 if not missing and "conn_capab_missing=1" in ev:
2111 raise Exception("conn_capab_missing reported unexpectedly")
2112
2113 def conn_capab_cred(domain=None, req_conn_capab=None):
2114 cred = default_cred(domain=domain)
2115 if req_conn_capab:
2116 cred['req_conn_capab'] = req_conn_capab
2117 return cred
2118
2119 def test_ap_hs20_req_conn_capab(dev, apdev):
2120 """Hotspot 2.0 network selection with req_conn_capab"""
2121 check_eap_capa(dev[0], "MSCHAPV2")
2122 bssid = apdev[0]['bssid']
2123 params = hs20_ap_params()
2124 hostapd.add_ap(apdev[0], params)
2125
2126 dev[0].hs20_enable()
2127 dev[0].scan_for_bss(bssid, freq="2412")
2128 logger.info("Not used in home network")
2129 values = conn_capab_cred(domain="example.com", req_conn_capab="6:1234")
2130 id = dev[0].add_cred_values(values)
2131 check_conn_capab_selection(dev[0], "home", False)
2132
2133 logger.info("Used in roaming network")
2134 dev[0].remove_cred(id)
2135 values = conn_capab_cred(domain="example.org", req_conn_capab="6:1234")
2136 id = dev[0].add_cred_values(values)
2137 check_conn_capab_selection(dev[0], "roaming", True)
2138
2139 logger.info("Verify that req_conn_capab does not prevent connection if no other network is available")
2140 check_auto_select(dev[0], bssid)
2141
2142 logger.info("Additional req_conn_capab checks")
2143
2144 dev[0].remove_cred(id)
2145 values = conn_capab_cred(domain="example.org", req_conn_capab="1:0")
2146 id = dev[0].add_cred_values(values)
2147 check_conn_capab_selection(dev[0], "roaming", True)
2148
2149 dev[0].remove_cred(id)
2150 values = conn_capab_cred(domain="example.org", req_conn_capab="17:5060")
2151 id = dev[0].add_cred_values(values)
2152 check_conn_capab_selection(dev[0], "roaming", True)
2153
2154 bssid2 = apdev[1]['bssid']
2155 params = hs20_ap_params(ssid="test-hs20b")
2156 params['hs20_conn_capab'] = [ "1:0:2", "6:22:1", "17:5060:0", "50:0:1" ]
2157 hostapd.add_ap(apdev[1], params)
2158
2159 dev[0].remove_cred(id)
2160 values = conn_capab_cred(domain="example.org", req_conn_capab="50")
2161 id = dev[0].add_cred_values(values)
2162 dev[0].set_cred(id, "req_conn_capab", "6:22")
2163 dev[0].scan_for_bss(bssid2, freq="2412")
2164 dev[0].request("INTERWORKING_SELECT freq=2412")
2165 for i in range(0, 2):
2166 ev = dev[0].wait_event(["INTERWORKING-AP"])
2167 if ev is None:
2168 raise Exception("Network selection timed out")
2169 if bssid in ev and "conn_capab_missing=1" not in ev:
2170 raise Exception("Missing protocol connection capability not reported")
2171 if bssid2 in ev and "conn_capab_missing=1" in ev:
2172 raise Exception("Protocol connection capability not reported correctly")
2173
2174 def test_ap_hs20_req_conn_capab2(dev, apdev):
2175 """Hotspot 2.0 network selection with req_conn_capab (not present)"""
2176 check_eap_capa(dev[0], "MSCHAPV2")
2177 bssid = apdev[0]['bssid']
2178 params = hs20_ap_params()
2179 del params['hs20_conn_capab']
2180 hostapd.add_ap(apdev[0], params)
2181
2182 dev[0].hs20_enable()
2183 dev[0].scan_for_bss(bssid, freq="2412")
2184 values = conn_capab_cred(domain="example.org", req_conn_capab="6:1234")
2185 id = dev[0].add_cred_values(values)
2186 check_conn_capab_selection(dev[0], "roaming", False)
2187
2188 def test_ap_hs20_req_conn_capab_and_roaming_partner_preference(dev, apdev):
2189 """Hotspot 2.0 and req_conn_capab with roaming partner preference"""
2190 check_eap_capa(dev[0], "MSCHAPV2")
2191 bssid = apdev[0]['bssid']
2192 params = hs20_ap_params()
2193 params['domain_name'] = "roaming.example.org"
2194 params['hs20_conn_capab'] = [ "1:0:2", "6:22:1", "17:5060:0", "50:0:1" ]
2195 hostapd.add_ap(apdev[0], params)
2196
2197 bssid2 = apdev[1]['bssid']
2198 params = hs20_ap_params(ssid="test-hs20-b")
2199 params['domain_name'] = "roaming.example.net"
2200 hostapd.add_ap(apdev[1], params)
2201
2202 values = default_cred()
2203 values['roaming_partner'] = "roaming.example.net,1,127,*"
2204 id = dev[0].add_cred_values(values)
2205 check_auto_select(dev[0], bssid2)
2206
2207 dev[0].set_cred(id, "req_conn_capab", "50")
2208 check_auto_select(dev[0], bssid)
2209
2210 dev[0].remove_cred(id)
2211 id = dev[0].add_cred_values(values)
2212 dev[0].set_cred(id, "req_conn_capab", "51")
2213 check_auto_select(dev[0], bssid2)
2214
2215 def check_bandwidth_selection(dev, type, below):
2216 dev.request("INTERWORKING_SELECT freq=2412")
2217 ev = dev.wait_event(["INTERWORKING-AP"])
2218 if ev is None:
2219 raise Exception("Network selection timed out")
2220 logger.debug("BSS entries:\n" + dev.request("BSS RANGE=ALL"))
2221 if "type=" + type not in ev:
2222 raise Exception("Unexpected network type")
2223 if below and "below_min_backhaul=1" not in ev:
2224 raise Exception("below_min_backhaul not reported")
2225 if not below and "below_min_backhaul=1" in ev:
2226 raise Exception("below_min_backhaul reported unexpectedly")
2227
2228 def bw_cred(domain=None, dl_home=None, ul_home=None, dl_roaming=None, ul_roaming=None):
2229 cred = default_cred(domain=domain)
2230 if dl_home:
2231 cred['min_dl_bandwidth_home'] = str(dl_home)
2232 if ul_home:
2233 cred['min_ul_bandwidth_home'] = str(ul_home)
2234 if dl_roaming:
2235 cred['min_dl_bandwidth_roaming'] = str(dl_roaming)
2236 if ul_roaming:
2237 cred['min_ul_bandwidth_roaming'] = str(ul_roaming)
2238 return cred
2239
2240 def test_ap_hs20_min_bandwidth_home(dev, apdev):
2241 """Hotspot 2.0 network selection with min bandwidth (home)"""
2242 check_eap_capa(dev[0], "MSCHAPV2")
2243 bssid = apdev[0]['bssid']
2244 params = hs20_ap_params()
2245 hostapd.add_ap(apdev[0], params)
2246
2247 dev[0].hs20_enable()
2248 dev[0].scan_for_bss(bssid, freq="2412")
2249 values = bw_cred(domain="example.com", dl_home=5490, ul_home=58)
2250 id = dev[0].add_cred_values(values)
2251 check_bandwidth_selection(dev[0], "home", False)
2252 dev[0].remove_cred(id)
2253
2254 values = bw_cred(domain="example.com", dl_home=5491, ul_home=58)
2255 id = dev[0].add_cred_values(values)
2256 check_bandwidth_selection(dev[0], "home", True)
2257 dev[0].remove_cred(id)
2258
2259 values = bw_cred(domain="example.com", dl_home=5490, ul_home=59)
2260 id = dev[0].add_cred_values(values)
2261 check_bandwidth_selection(dev[0], "home", True)
2262 dev[0].remove_cred(id)
2263
2264 values = bw_cred(domain="example.com", dl_home=5491, ul_home=59)
2265 id = dev[0].add_cred_values(values)
2266 check_bandwidth_selection(dev[0], "home", True)
2267 check_auto_select(dev[0], bssid)
2268
2269 bssid2 = apdev[1]['bssid']
2270 params = hs20_ap_params(ssid="test-hs20-b")
2271 params['hs20_wan_metrics'] = "01:8000:1000:1:1:3000"
2272 hostapd.add_ap(apdev[1], params)
2273
2274 check_auto_select(dev[0], bssid2)
2275
2276 def test_ap_hs20_min_bandwidth_home2(dev, apdev):
2277 """Hotspot 2.0 network selection with min bandwidth - special cases"""
2278 check_eap_capa(dev[0], "MSCHAPV2")
2279 bssid = apdev[0]['bssid']
2280 params = hs20_ap_params()
2281 hapd = hostapd.add_ap(apdev[0], params)
2282
2283 dev[0].hs20_enable()
2284 dev[0].scan_for_bss(bssid, freq="2412")
2285 values = bw_cred(domain="example.com", dl_home=5490, ul_home=58)
2286 id = dev[0].add_cred_values(values)
2287 check_bandwidth_selection(dev[0], "home", False)
2288
2289 logger.info("WAN link at capacity")
2290 hapd.set('hs20_wan_metrics', "09:8000:1000:80:240:3000")
2291 check_bandwidth_selection(dev[0], "home", True)
2292
2293 logger.info("Downlink/Uplink Load was not measured")
2294 hapd.set('hs20_wan_metrics', "01:8000:1000:80:240:0")
2295 check_bandwidth_selection(dev[0], "home", False)
2296
2297 logger.info("Uplink and Downlink max values")
2298 hapd.set('hs20_wan_metrics', "01:4294967295:4294967295:80:240:3000")
2299 check_bandwidth_selection(dev[0], "home", False)
2300
2301 dev[0].remove_cred(id)
2302
2303 def test_ap_hs20_min_bandwidth_home_hidden_ssid_in_scan_res(dev, apdev):
2304 """Hotspot 2.0 network selection with min bandwidth (home) while hidden SSID is included in scan results"""
2305 check_eap_capa(dev[0], "MSCHAPV2")
2306 bssid = apdev[0]['bssid']
2307
2308 hapd = hostapd.add_ap(apdev[0], { "ssid": 'secret',
2309 "ignore_broadcast_ssid": "1" })
2310 dev[0].scan_for_bss(bssid, freq=2412)
2311 hapd.disable()
2312 hapd_global = hostapd.HostapdGlobal(apdev[0])
2313 hapd_global.flush()
2314 hapd_global.remove(apdev[0]['ifname'])
2315
2316 params = hs20_ap_params()
2317 hostapd.add_ap(apdev[0], params)
2318
2319 dev[0].hs20_enable()
2320 dev[0].scan_for_bss(bssid, freq="2412")
2321 values = bw_cred(domain="example.com", dl_home=5490, ul_home=58)
2322 id = dev[0].add_cred_values(values)
2323 check_bandwidth_selection(dev[0], "home", False)
2324 dev[0].remove_cred(id)
2325
2326 values = bw_cred(domain="example.com", dl_home=5491, ul_home=58)
2327 id = dev[0].add_cred_values(values)
2328 check_bandwidth_selection(dev[0], "home", True)
2329 dev[0].remove_cred(id)
2330
2331 values = bw_cred(domain="example.com", dl_home=5490, ul_home=59)
2332 id = dev[0].add_cred_values(values)
2333 check_bandwidth_selection(dev[0], "home", True)
2334 dev[0].remove_cred(id)
2335
2336 values = bw_cred(domain="example.com", dl_home=5491, ul_home=59)
2337 id = dev[0].add_cred_values(values)
2338 check_bandwidth_selection(dev[0], "home", True)
2339 check_auto_select(dev[0], bssid)
2340
2341 bssid2 = apdev[1]['bssid']
2342 params = hs20_ap_params(ssid="test-hs20-b")
2343 params['hs20_wan_metrics'] = "01:8000:1000:1:1:3000"
2344 hostapd.add_ap(apdev[1], params)
2345
2346 check_auto_select(dev[0], bssid2)
2347
2348 dev[0].flush_scan_cache()
2349
2350 def test_ap_hs20_min_bandwidth_roaming(dev, apdev):
2351 """Hotspot 2.0 network selection with min bandwidth (roaming)"""
2352 check_eap_capa(dev[0], "MSCHAPV2")
2353 bssid = apdev[0]['bssid']
2354 params = hs20_ap_params()
2355 hostapd.add_ap(apdev[0], params)
2356
2357 dev[0].hs20_enable()
2358 dev[0].scan_for_bss(bssid, freq="2412")
2359 values = bw_cred(domain="example.org", dl_roaming=5490, ul_roaming=58)
2360 id = dev[0].add_cred_values(values)
2361 check_bandwidth_selection(dev[0], "roaming", False)
2362 dev[0].remove_cred(id)
2363
2364 values = bw_cred(domain="example.org", dl_roaming=5491, ul_roaming=58)
2365 id = dev[0].add_cred_values(values)
2366 check_bandwidth_selection(dev[0], "roaming", True)
2367 dev[0].remove_cred(id)
2368
2369 values = bw_cred(domain="example.org", dl_roaming=5490, ul_roaming=59)
2370 id = dev[0].add_cred_values(values)
2371 check_bandwidth_selection(dev[0], "roaming", True)
2372 dev[0].remove_cred(id)
2373
2374 values = bw_cred(domain="example.org", dl_roaming=5491, ul_roaming=59)
2375 id = dev[0].add_cred_values(values)
2376 check_bandwidth_selection(dev[0], "roaming", True)
2377 check_auto_select(dev[0], bssid)
2378
2379 bssid2 = apdev[1]['bssid']
2380 params = hs20_ap_params(ssid="test-hs20-b")
2381 params['hs20_wan_metrics'] = "01:8000:1000:1:1:3000"
2382 hostapd.add_ap(apdev[1], params)
2383
2384 check_auto_select(dev[0], bssid2)
2385
2386 def test_ap_hs20_min_bandwidth_and_roaming_partner_preference(dev, apdev):
2387 """Hotspot 2.0 and minimum bandwidth with roaming partner preference"""
2388 check_eap_capa(dev[0], "MSCHAPV2")
2389 bssid = apdev[0]['bssid']
2390 params = hs20_ap_params()
2391 params['domain_name'] = "roaming.example.org"
2392 params['hs20_wan_metrics'] = "01:8000:1000:1:1:3000"
2393 hostapd.add_ap(apdev[0], params)
2394
2395 bssid2 = apdev[1]['bssid']
2396 params = hs20_ap_params(ssid="test-hs20-b")
2397 params['domain_name'] = "roaming.example.net"
2398 hostapd.add_ap(apdev[1], params)
2399
2400 values = default_cred()
2401 values['roaming_partner'] = "roaming.example.net,1,127,*"
2402 id = dev[0].add_cred_values(values)
2403 check_auto_select(dev[0], bssid2)
2404
2405 dev[0].set_cred(id, "min_dl_bandwidth_roaming", "6000")
2406 check_auto_select(dev[0], bssid)
2407
2408 dev[0].set_cred(id, "min_dl_bandwidth_roaming", "10000")
2409 check_auto_select(dev[0], bssid2)
2410
2411 def test_ap_hs20_min_bandwidth_no_wan_metrics(dev, apdev):
2412 """Hotspot 2.0 network selection with min bandwidth but no WAN Metrics"""
2413 bssid = apdev[0]['bssid']
2414 params = hs20_ap_params()
2415 del params['hs20_wan_metrics']
2416 hostapd.add_ap(apdev[0], params)
2417
2418 dev[0].hs20_enable()
2419 dev[0].scan_for_bss(bssid, freq="2412")
2420 values = bw_cred(domain="example.com", dl_home=10000, ul_home=10000,
2421 dl_roaming=10000, ul_roaming=10000)
2422 dev[0].add_cred_values(values)
2423 check_bandwidth_selection(dev[0], "home", False)
2424
2425 def test_ap_hs20_deauth_req_ess(dev, apdev):
2426 """Hotspot 2.0 connection and deauthentication request for ESS"""
2427 check_eap_capa(dev[0], "MSCHAPV2")
2428 try:
2429 _test_ap_hs20_deauth_req_ess(dev, apdev)
2430 finally:
2431 dev[0].request("SET pmf 0")
2432
2433 def _test_ap_hs20_deauth_req_ess(dev, apdev):
2434 dev[0].request("SET pmf 2")
2435 eap_test(dev[0], apdev[0], "21[3:26]", "TTLS", "user")
2436 dev[0].dump_monitor()
2437 addr = dev[0].p2p_interface_addr()
2438 hapd = hostapd.Hostapd(apdev[0]['ifname'])
2439 hapd.request("HS20_DEAUTH_REQ " + addr + " 1 120 http://example.com/")
2440 ev = dev[0].wait_event(["HS20-DEAUTH-IMMINENT-NOTICE"])
2441 if ev is None:
2442 raise Exception("Timeout on deauth imminent notice")
2443 if "1 120 http://example.com/" not in ev:
2444 raise Exception("Unexpected deauth imminent notice: " + ev)
2445 hapd.request("DEAUTHENTICATE " + addr)
2446 dev[0].wait_disconnected(timeout=10)
2447 if "[TEMP-DISABLED]" not in dev[0].list_networks()[0]['flags']:
2448 raise Exception("Network not marked temporarily disabled")
2449 ev = dev[0].wait_event(["SME: Trying to authenticate",
2450 "Trying to associate",
2451 "CTRL-EVENT-CONNECTED"], timeout=5)
2452 if ev is not None:
2453 raise Exception("Unexpected connection attempt")
2454
2455 def test_ap_hs20_deauth_req_bss(dev, apdev):
2456 """Hotspot 2.0 connection and deauthentication request for BSS"""
2457 check_eap_capa(dev[0], "MSCHAPV2")
2458 try:
2459 _test_ap_hs20_deauth_req_bss(dev, apdev)
2460 finally:
2461 dev[0].request("SET pmf 0")
2462
2463 def _test_ap_hs20_deauth_req_bss(dev, apdev):
2464 dev[0].request("SET pmf 2")
2465 eap_test(dev[0], apdev[0], "21[3:26]", "TTLS", "user")
2466 dev[0].dump_monitor()
2467 addr = dev[0].p2p_interface_addr()
2468 hapd = hostapd.Hostapd(apdev[0]['ifname'])
2469 hapd.request("HS20_DEAUTH_REQ " + addr + " 0 120 http://example.com/")
2470 ev = dev[0].wait_event(["HS20-DEAUTH-IMMINENT-NOTICE"])
2471 if ev is None:
2472 raise Exception("Timeout on deauth imminent notice")
2473 if "0 120 http://example.com/" not in ev:
2474 raise Exception("Unexpected deauth imminent notice: " + ev)
2475 hapd.request("DEAUTHENTICATE " + addr + " reason=4")
2476 ev = dev[0].wait_disconnected(timeout=10)
2477 if "reason=4" not in ev:
2478 raise Exception("Unexpected disconnection reason")
2479 if "[TEMP-DISABLED]" not in dev[0].list_networks()[0]['flags']:
2480 raise Exception("Network not marked temporarily disabled")
2481 ev = dev[0].wait_event(["SME: Trying to authenticate",
2482 "Trying to associate",
2483 "CTRL-EVENT-CONNECTED"], timeout=5)
2484 if ev is not None:
2485 raise Exception("Unexpected connection attempt")
2486
2487 def test_ap_hs20_deauth_req_from_radius(dev, apdev):
2488 """Hotspot 2.0 connection and deauthentication request from RADIUS"""
2489 check_eap_capa(dev[0], "MSCHAPV2")
2490 try:
2491 _test_ap_hs20_deauth_req_from_radius(dev, apdev)
2492 finally:
2493 dev[0].request("SET pmf 0")
2494
2495 def _test_ap_hs20_deauth_req_from_radius(dev, apdev):
2496 bssid = apdev[0]['bssid']
2497 params = hs20_ap_params()
2498 params['nai_realm'] = [ "0,example.com,21[2:4]" ]
2499 params['hs20_deauth_req_timeout'] = "2"
2500 hostapd.add_ap(apdev[0], params)
2501
2502 dev[0].request("SET pmf 2")
2503 dev[0].hs20_enable()
2504 dev[0].add_cred_values({ 'realm': "example.com",
2505 'username': "hs20-deauth-test",
2506 'password': "password" })
2507 interworking_select(dev[0], bssid, freq="2412")
2508 interworking_connect(dev[0], bssid, "TTLS")
2509 ev = dev[0].wait_event(["HS20-DEAUTH-IMMINENT-NOTICE"], timeout=5)
2510 if ev is None:
2511 raise Exception("Timeout on deauth imminent notice")
2512 if " 1 100" not in ev:
2513 raise Exception("Unexpected deauth imminent contents")
2514 dev[0].wait_disconnected(timeout=3)
2515
2516 def test_ap_hs20_deauth_req_without_pmf(dev, apdev):
2517 """Hotspot 2.0 connection and deauthentication request without PMF"""
2518 check_eap_capa(dev[0], "MSCHAPV2")
2519 dev[0].request("SET pmf 0")
2520 eap_test(dev[0], apdev[0], "21[3:26]", "TTLS", "user", release=1)
2521 dev[0].dump_monitor()
2522 id = int(dev[0].get_status_field("id"))
2523 dev[0].set_network(id, "ieee80211w", "0")
2524 dev[0].request("DISCONNECT")
2525 dev[0].wait_disconnected()
2526 dev[0].select_network(id, freq=2412)
2527 dev[0].wait_connected()
2528 addr = dev[0].own_addr()
2529 hapd = hostapd.Hostapd(apdev[0]['ifname'])
2530 hapd.request("HS20_DEAUTH_REQ " + addr + " 1 120 http://example.com/")
2531 ev = dev[0].wait_event(["HS20-DEAUTH-IMMINENT-NOTICE"], timeout=0.2)
2532 if ev is not None:
2533 raise Exception("Deauth imminent notice without PMF accepted")
2534 with alloc_fail(hapd, 1, "wpabuf_alloc;hostapd_ctrl_iface_hs20_deauth_req"):
2535 if "FAIL" not in hapd.request("HS20_DEAUTH_REQ " + addr + " 1 120 http://example.com/"):
2536 raise Exception("HS20_DEAUTH_REQ accepted during OOM")
2537
2538 def test_ap_hs20_remediation_required(dev, apdev):
2539 """Hotspot 2.0 connection and remediation required from RADIUS"""
2540 check_eap_capa(dev[0], "MSCHAPV2")
2541 try:
2542 _test_ap_hs20_remediation_required(dev, apdev)
2543 finally:
2544 dev[0].request("SET pmf 0")
2545
2546 def _test_ap_hs20_remediation_required(dev, apdev):
2547 bssid = apdev[0]['bssid']
2548 params = hs20_ap_params()
2549 params['nai_realm'] = [ "0,example.com,21[2:4]" ]
2550 hostapd.add_ap(apdev[0], params)
2551
2552 dev[0].request("SET pmf 1")
2553 dev[0].hs20_enable()
2554 dev[0].add_cred_values({ 'realm': "example.com",
2555 'username': "hs20-subrem-test",
2556 'password': "password" })
2557 interworking_select(dev[0], bssid, freq="2412")
2558 interworking_connect(dev[0], bssid, "TTLS")
2559 ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=5)
2560 if ev is None:
2561 raise Exception("Timeout on subscription remediation notice")
2562 if " 1 https://example.com/" not in ev:
2563 raise Exception("Unexpected subscription remediation event contents")
2564
2565 def test_ap_hs20_remediation_required_ctrl(dev, apdev):
2566 """Hotspot 2.0 connection and subrem from ctrl_iface"""
2567 check_eap_capa(dev[0], "MSCHAPV2")
2568 try:
2569 _test_ap_hs20_remediation_required_ctrl(dev, apdev)
2570 finally:
2571 dev[0].request("SET pmf 0")
2572
2573 def _test_ap_hs20_remediation_required_ctrl(dev, apdev):
2574 bssid = apdev[0]['bssid']
2575 addr = dev[0].own_addr()
2576 params = hs20_ap_params()
2577 params['nai_realm'] = [ "0,example.com,21[2:4]" ]
2578 hapd = hostapd.add_ap(apdev[0], params)
2579
2580 dev[0].request("SET pmf 1")
2581 dev[0].hs20_enable()
2582 dev[0].add_cred_values(default_cred())
2583 interworking_select(dev[0], bssid, freq="2412")
2584 interworking_connect(dev[0], bssid, "TTLS")
2585
2586 hapd.request("HS20_WNM_NOTIF " + addr + " https://example.com/")
2587 ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=5)
2588 if ev is None:
2589 raise Exception("Timeout on subscription remediation notice")
2590 if " 1 https://example.com/" not in ev:
2591 raise Exception("Unexpected subscription remediation event contents")
2592
2593 hapd.request("HS20_WNM_NOTIF " + addr)
2594 ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=5)
2595 if ev is None:
2596 raise Exception("Timeout on subscription remediation notice")
2597 if not ev.endswith("HS20-SUBSCRIPTION-REMEDIATION "):
2598 raise Exception("Unexpected subscription remediation event contents: " + ev)
2599
2600 if "FAIL" not in hapd.request("HS20_WNM_NOTIF "):
2601 raise Exception("Unexpected HS20_WNM_NOTIF success")
2602 if "FAIL" not in hapd.request("HS20_WNM_NOTIF foo"):
2603 raise Exception("Unexpected HS20_WNM_NOTIF success")
2604 if "FAIL" not in hapd.request("HS20_WNM_NOTIF " + addr + " https://12345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678927.very.long.example.com/"):
2605 raise Exception("Unexpected HS20_WNM_NOTIF success")
2606 if "OK" not in hapd.request("HS20_WNM_NOTIF " + addr + " "):
2607 raise Exception("HS20_WNM_NOTIF failed with empty URL")
2608
2609 def test_ap_hs20_session_info(dev, apdev):
2610 """Hotspot 2.0 connection and session information from RADIUS"""
2611 check_eap_capa(dev[0], "MSCHAPV2")
2612 try:
2613 _test_ap_hs20_session_info(dev, apdev)
2614 finally:
2615 dev[0].request("SET pmf 0")
2616
2617 def _test_ap_hs20_session_info(dev, apdev):
2618 bssid = apdev[0]['bssid']
2619 params = hs20_ap_params()
2620 params['nai_realm'] = [ "0,example.com,21[2:4]" ]
2621 hostapd.add_ap(apdev[0], params)
2622
2623 dev[0].request("SET pmf 1")
2624 dev[0].hs20_enable()
2625 dev[0].add_cred_values({ 'realm': "example.com",
2626 'username': "hs20-session-info-test",
2627 'password': "password" })
2628 interworking_select(dev[0], bssid, freq="2412")
2629 interworking_connect(dev[0], bssid, "TTLS")
2630 ev = dev[0].wait_event(["ESS-DISASSOC-IMMINENT"], timeout=10)
2631 if ev is None:
2632 raise Exception("Timeout on ESS disassociation imminent notice")
2633 if " 1 59904 https://example.com/" not in ev:
2634 raise Exception("Unexpected ESS disassociation imminent event contents")
2635 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"])
2636 if ev is None:
2637 raise Exception("Scan not started")
2638 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=30)
2639 if ev is None:
2640 raise Exception("Scan not completed")
2641
2642 def test_ap_hs20_osen(dev, apdev):
2643 """Hotspot 2.0 OSEN connection"""
2644 params = { 'ssid': "osen",
2645 'osen': "1",
2646 'auth_server_addr': "127.0.0.1",
2647 'auth_server_port': "1812",
2648 'auth_server_shared_secret': "radius" }
2649 hostapd.add_ap(apdev[0], params)
2650
2651 dev[1].connect("osen", key_mgmt="NONE", scan_freq="2412",
2652 wait_connect=False)
2653 dev[2].connect("osen", key_mgmt="NONE", wep_key0='"hello"',
2654 scan_freq="2412", wait_connect=False)
2655 dev[0].flush_scan_cache()
2656 dev[0].connect("osen", proto="OSEN", key_mgmt="OSEN", pairwise="CCMP",
2657 group="GTK_NOT_USED CCMP",
2658 eap="WFA-UNAUTH-TLS", identity="osen@example.com",
2659 ca_cert="auth_serv/ca.pem",
2660 scan_freq="2412")
2661 res = dev[0].get_bss(apdev[0]['bssid'])['flags']
2662 if "[OSEN-OSEN-CCMP]" not in res:
2663 raise Exception("OSEN not reported in BSS")
2664 if "[WEP]" in res:
2665 raise Exception("WEP reported in BSS")
2666 res = dev[0].request("SCAN_RESULTS")
2667 if "[OSEN-OSEN-CCMP]" not in res:
2668 raise Exception("OSEN not reported in SCAN_RESULTS")
2669
2670 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
2671 wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
2672 wpas.connect("osen", proto="OSEN", key_mgmt="OSEN", pairwise="CCMP",
2673 group="GTK_NOT_USED CCMP",
2674 eap="WFA-UNAUTH-TLS", identity="osen@example.com",
2675 ca_cert="auth_serv/ca.pem",
2676 scan_freq="2412")
2677 wpas.request("DISCONNECT")
2678
2679 def test_ap_hs20_osen_single_ssid(dev, apdev):
2680 """Hotspot 2.0 OSEN-single-SSID connection"""
2681 bssid = apdev[0]['bssid']
2682 params = hs20_ap_params()
2683 params['wpa_key_mgmt'] = "WPA-EAP OSEN"
2684 params['hessid'] = bssid
2685 hapd = hostapd.add_ap(apdev[0], params)
2686
2687 # RSN-OSEN (for OSU)
2688 dev[0].connect("test-hs20", proto="OSEN", key_mgmt="OSEN", pairwise="CCMP",
2689 group="CCMP GTK_NOT_USED",
2690 eap="WFA-UNAUTH-TLS", identity="osen@example.com",
2691 ca_cert="auth_serv/ca.pem", ieee80211w='2',
2692 scan_freq="2412")
2693 # RSN-EAP (for data connection)
2694 dev[1].connect("test-hs20", key_mgmt="WPA-EAP", eap="TTLS",
2695 identity="hs20-test", password="password",
2696 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
2697 pairwise="CCMP", group="CCMP",
2698 ieee80211w='2', scan_freq="2412")
2699
2700 res = dev[0].get_bss(apdev[0]['bssid'])['flags']
2701 if "[WPA2-EAP+OSEN-CCMP]" not in res:
2702 raise Exception("OSEN not reported in BSS")
2703 if "[WEP]" in res:
2704 raise Exception("WEP reported in BSS")
2705 res = dev[0].request("SCAN_RESULTS")
2706 if "[WPA2-EAP+OSEN-CCMP]" not in res:
2707 raise Exception("OSEN not reported in SCAN_RESULTS")
2708
2709 hwsim_utils.test_connectivity(dev[1], hapd)
2710 hwsim_utils.test_connectivity(dev[0], hapd, broadcast=False)
2711 hwsim_utils.test_connectivity(dev[0], hapd, timeout=1,
2712 success_expected=False)
2713
2714 def test_ap_hs20_network_preference(dev, apdev):
2715 """Hotspot 2.0 network selection with preferred home network"""
2716 check_eap_capa(dev[0], "MSCHAPV2")
2717 bssid = apdev[0]['bssid']
2718 params = hs20_ap_params()
2719 hostapd.add_ap(apdev[0], params)
2720
2721 dev[0].hs20_enable()
2722 values = { 'realm': "example.com",
2723 'username': "hs20-test",
2724 'password': "password",
2725 'domain': "example.com" }
2726 dev[0].add_cred_values(values)
2727
2728 id = dev[0].add_network()
2729 dev[0].set_network_quoted(id, "ssid", "home")
2730 dev[0].set_network_quoted(id, "psk", "12345678")
2731 dev[0].set_network(id, "priority", "1")
2732 dev[0].request("ENABLE_NETWORK %s no-connect" % id)
2733
2734 dev[0].scan_for_bss(bssid, freq="2412")
2735 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2736 ev = dev[0].wait_connected(timeout=15)
2737 if bssid not in ev:
2738 raise Exception("Unexpected network selected")
2739
2740 bssid2 = apdev[1]['bssid']
2741 params = hostapd.wpa2_params(ssid="home", passphrase="12345678")
2742 hostapd.add_ap(apdev[1], params)
2743
2744 dev[0].scan_for_bss(bssid2, freq="2412")
2745 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2746 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
2747 "INTERWORKING-ALREADY-CONNECTED" ], timeout=15)
2748 if ev is None:
2749 raise Exception("Connection timed out")
2750 if "INTERWORKING-ALREADY-CONNECTED" in ev:
2751 raise Exception("No roam to higher priority network")
2752 if bssid2 not in ev:
2753 raise Exception("Unexpected network selected")
2754
2755 def test_ap_hs20_network_preference2(dev, apdev):
2756 """Hotspot 2.0 network selection with preferred credential"""
2757 check_eap_capa(dev[0], "MSCHAPV2")
2758 bssid2 = apdev[1]['bssid']
2759 params = hostapd.wpa2_params(ssid="home", passphrase="12345678")
2760 hostapd.add_ap(apdev[1], params)
2761
2762 dev[0].hs20_enable()
2763 values = { 'realm': "example.com",
2764 'username': "hs20-test",
2765 'password': "password",
2766 'domain': "example.com",
2767 'priority': "1" }
2768 dev[0].add_cred_values(values)
2769
2770 id = dev[0].add_network()
2771 dev[0].set_network_quoted(id, "ssid", "home")
2772 dev[0].set_network_quoted(id, "psk", "12345678")
2773 dev[0].request("ENABLE_NETWORK %s no-connect" % id)
2774
2775 dev[0].scan_for_bss(bssid2, freq="2412")
2776 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2777 ev = dev[0].wait_connected(timeout=15)
2778 if bssid2 not in ev:
2779 raise Exception("Unexpected network selected")
2780
2781 bssid = apdev[0]['bssid']
2782 params = hs20_ap_params()
2783 hostapd.add_ap(apdev[0], params)
2784
2785 dev[0].scan_for_bss(bssid, freq="2412")
2786 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2787 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
2788 "INTERWORKING-ALREADY-CONNECTED" ], timeout=15)
2789 if ev is None:
2790 raise Exception("Connection timed out")
2791 if "INTERWORKING-ALREADY-CONNECTED" in ev:
2792 raise Exception("No roam to higher priority network")
2793 if bssid not in ev:
2794 raise Exception("Unexpected network selected")
2795
2796 def test_ap_hs20_network_preference3(dev, apdev):
2797 """Hotspot 2.0 network selection with two credential (one preferred)"""
2798 check_eap_capa(dev[0], "MSCHAPV2")
2799 bssid = apdev[0]['bssid']
2800 params = hs20_ap_params()
2801 hostapd.add_ap(apdev[0], params)
2802
2803 bssid2 = apdev[1]['bssid']
2804 params = hs20_ap_params(ssid="test-hs20b")
2805 params['nai_realm'] = "0,example.org,13[5:6],21[2:4][5:7]"
2806 hostapd.add_ap(apdev[1], params)
2807
2808 dev[0].hs20_enable()
2809 values = { 'realm': "example.com",
2810 'username': "hs20-test",
2811 'password': "password",
2812 'priority': "1" }
2813 dev[0].add_cred_values(values)
2814 values = { 'realm': "example.org",
2815 'username': "hs20-test",
2816 'password': "password" }
2817 id = dev[0].add_cred_values(values)
2818
2819 dev[0].scan_for_bss(bssid, freq="2412")
2820 dev[0].scan_for_bss(bssid2, freq="2412")
2821 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2822 ev = dev[0].wait_connected(timeout=15)
2823 if bssid not in ev:
2824 raise Exception("Unexpected network selected")
2825
2826 dev[0].set_cred(id, "priority", "2")
2827 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2828 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
2829 "INTERWORKING-ALREADY-CONNECTED" ], timeout=15)
2830 if ev is None:
2831 raise Exception("Connection timed out")
2832 if "INTERWORKING-ALREADY-CONNECTED" in ev:
2833 raise Exception("No roam to higher priority network")
2834 if bssid2 not in ev:
2835 raise Exception("Unexpected network selected")
2836
2837 def test_ap_hs20_network_preference4(dev, apdev):
2838 """Hotspot 2.0 network selection with username vs. SIM credential"""
2839 check_eap_capa(dev[0], "MSCHAPV2")
2840 bssid = apdev[0]['bssid']
2841 params = hs20_ap_params()
2842 hostapd.add_ap(apdev[0], params)
2843
2844 bssid2 = apdev[1]['bssid']
2845 params = hs20_ap_params(ssid="test-hs20b")
2846 params['hessid'] = bssid2
2847 params['anqp_3gpp_cell_net'] = "555,444"
2848 params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org"
2849 hostapd.add_ap(apdev[1], params)
2850
2851 dev[0].hs20_enable()
2852 values = { 'realm': "example.com",
2853 'username': "hs20-test",
2854 'password': "password",
2855 'priority': "1" }
2856 dev[0].add_cred_values(values)
2857 values = { 'imsi': "555444-333222111",
2858 'eap': "SIM",
2859 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123" }
2860 id = dev[0].add_cred_values(values)
2861
2862 dev[0].scan_for_bss(bssid, freq="2412")
2863 dev[0].scan_for_bss(bssid2, freq="2412")
2864 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2865 ev = dev[0].wait_connected(timeout=15)
2866 if bssid not in ev:
2867 raise Exception("Unexpected network selected")
2868
2869 dev[0].set_cred(id, "priority", "2")
2870 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2871 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
2872 "INTERWORKING-ALREADY-CONNECTED" ], timeout=15)
2873 if ev is None:
2874 raise Exception("Connection timed out")
2875 if "INTERWORKING-ALREADY-CONNECTED" in ev:
2876 raise Exception("No roam to higher priority network")
2877 if bssid2 not in ev:
2878 raise Exception("Unexpected network selected")
2879
2880 def test_ap_hs20_interworking_select_blocking_scan(dev, apdev):
2881 """Ongoing INTERWORKING_SELECT blocking SCAN"""
2882 check_eap_capa(dev[0], "MSCHAPV2")
2883 bssid = apdev[0]['bssid']
2884 params = hs20_ap_params()
2885 hostapd.add_ap(apdev[0], params)
2886
2887 dev[0].hs20_enable()
2888 values = { 'realm': "example.com",
2889 'username': "hs20-test",
2890 'password': "password",
2891 'domain': "example.com" }
2892 dev[0].add_cred_values(values)
2893
2894 dev[0].scan_for_bss(bssid, freq="2412")
2895 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2896 if "FAIL-BUSY" not in dev[0].request("SCAN"):
2897 raise Exception("Unexpected SCAN command result")
2898 dev[0].wait_connected(timeout=15)
2899
2900 def test_ap_hs20_fetch_osu(dev, apdev):
2901 """Hotspot 2.0 OSU provider and icon fetch"""
2902 bssid = apdev[0]['bssid']
2903 params = hs20_ap_params()
2904 params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
2905 params['osu_ssid'] = '"HS 2.0 OSU open"'
2906 params['osu_method_list'] = "1"
2907 params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
2908 params['osu_icon'] = "w1fi_logo"
2909 params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
2910 params['osu_server_uri'] = "https://example.com/osu/"
2911 hostapd.add_ap(apdev[0], params)
2912
2913 bssid2 = apdev[1]['bssid']
2914 params = hs20_ap_params(ssid="test-hs20b")
2915 params['hessid'] = bssid2
2916 params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
2917 params['osu_ssid'] = '"HS 2.0 OSU OSEN"'
2918 params['osu_method_list'] = "0"
2919 params['osu_nai'] = "osen@example.com"
2920 params['osu_friendly_name'] = [ "eng:Test2 OSU", "fin:Testi2-OSU" ]
2921 params['osu_icon'] = "w1fi_logo"
2922 params['osu_service_desc'] = [ "eng:Example services2", "fin:Esimerkkipalveluja2" ]
2923 params['osu_server_uri'] = "https://example.org/osu/"
2924 hostapd.add_ap(apdev[1], params)
2925
2926 with open("w1fi_logo.png", "r") as f:
2927 orig_logo = f.read()
2928 dev[0].hs20_enable()
2929 dir = "/tmp/osu-fetch"
2930 if os.path.isdir(dir):
2931 files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
2932 for f in files:
2933 os.remove(dir + "/" + f)
2934 else:
2935 try:
2936 os.makedirs(dir)
2937 except:
2938 pass
2939 try:
2940 dev[1].scan_for_bss(bssid, freq="2412")
2941 dev[2].scan_for_bss(bssid, freq="2412")
2942 dev[0].request("SET osu_dir " + dir)
2943 dev[0].request("FETCH_OSU")
2944 if "FAIL" not in dev[1].request("HS20_ICON_REQUEST foo w1fi_logo"):
2945 raise Exception("Invalid HS20_ICON_REQUEST accepted")
2946 if "OK" not in dev[1].request("HS20_ICON_REQUEST " + bssid + " w1fi_logo"):
2947 raise Exception("HS20_ICON_REQUEST failed")
2948 if "OK" not in dev[2].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
2949 raise Exception("REQ_HS20_ICON failed")
2950 icons = 0
2951 while True:
2952 ev = dev[0].wait_event(["OSU provider fetch completed",
2953 "RX-HS20-ANQP-ICON"], timeout=15)
2954 if ev is None:
2955 raise Exception("Timeout on OSU fetch")
2956 if "OSU provider fetch completed" in ev:
2957 break
2958 if "RX-HS20-ANQP-ICON" in ev:
2959 with open(ev.split(' ')[1], "r") as f:
2960 logo = f.read()
2961 if logo == orig_logo:
2962 icons += 1
2963
2964 with open(dir + "/osu-providers.txt", "r") as f:
2965 prov = f.read()
2966 logger.debug("osu-providers.txt: " + prov)
2967 if "OSU-PROVIDER " + bssid not in prov:
2968 raise Exception("Missing OSU_PROVIDER(1)")
2969 if "OSU-PROVIDER " + bssid2 not in prov:
2970 raise Exception("Missing OSU_PROVIDER(2)")
2971 finally:
2972 files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
2973 for f in files:
2974 os.remove(dir + "/" + f)
2975 os.rmdir(dir)
2976
2977 if icons != 2:
2978 raise Exception("Unexpected number of icons fetched")
2979
2980 ev = dev[1].wait_event(["GAS-QUERY-START"], timeout=5)
2981 if ev is None:
2982 raise Exception("Timeout on GAS-QUERY-DONE")
2983 ev = dev[1].wait_event(["GAS-QUERY-DONE"], timeout=5)
2984 if ev is None:
2985 raise Exception("Timeout on GAS-QUERY-DONE")
2986 if "freq=2412 status_code=0 result=SUCCESS" not in ev:
2987 raise Exception("Unexpected GAS-QUERY-DONE: " + ev)
2988 ev = dev[1].wait_event(["RX-HS20-ANQP"], timeout=15)
2989 if ev is None:
2990 raise Exception("Timeout on icon fetch")
2991 if "Icon Binary File" not in ev:
2992 raise Exception("Unexpected ANQP element")
2993
2994 ev = dev[2].wait_event(["RX-HS20-ICON"], timeout=5)
2995 if ev is None:
2996 raise Exception("Timeout on RX-HS20-ICON")
2997 event_icon_len = ev.split(' ')[3]
2998 if " w1fi_logo " not in ev:
2999 raise Exception("RX-HS20-ICON did not have the expected file name")
3000 if bssid not in ev:
3001 raise Exception("RX-HS20-ICON did not have the expected BSSID")
3002 if "FAIL" in dev[2].request("GET_HS20_ICON " + bssid + " w1fi_logo 0 10"):
3003 raise Exception("GET_HS20_ICON 0..10 failed")
3004 if "FAIL" in dev[2].request("GET_HS20_ICON " + bssid + " w1fi_logo 5 10"):
3005 raise Exception("GET_HS20_ICON 5..15 failed")
3006 if "FAIL" not in dev[2].request("GET_HS20_ICON " + bssid + " w1fi_logo 100000 10"):
3007 raise Exception("Unexpected success of GET_HS20_ICON with too large offset")
3008 if "FAIL" not in dev[2].request("GET_HS20_ICON " + bssid + " no_such_logo 0 10"):
3009 raise Exception("GET_HS20_ICON for not existing icon succeeded")
3010 if "FAIL" not in dev[2].request("GET_HS20_ICON " + bssid + " w1fi_logo 0 3070"):
3011 raise Exception("GET_HS20_ICON with too many output bytes to fit the buffer succeeded")
3012 if "FAIL" not in dev[2].request("GET_HS20_ICON " + bssid + " w1fi_logo 0 0"):
3013 raise Exception("GET_HS20_ICON 0..0 succeeded")
3014 icon = ""
3015 pos = 0
3016 while True:
3017 if pos > 100000:
3018 raise Exception("Unexpectedly long icon")
3019 res = dev[2].request("GET_HS20_ICON " + bssid + " w1fi_logo %d 1000" % pos)
3020 if res.startswith("FAIL"):
3021 break
3022 icon += base64.b64decode(res)
3023 pos += 1000
3024 hex = binascii.hexlify(icon)
3025 if not hex.startswith("0009696d6167652f706e677d1d"):
3026 raise Exception("Unexpected beacon binary header: " + hex)
3027 with open('w1fi_logo.png', 'r') as f:
3028 data = f.read()
3029 if icon[13:] != data:
3030 raise Exception("Unexpected icon data")
3031 if len(icon) != int(event_icon_len):
3032 raise Exception("Unexpected RX-HS20-ICON event length: " + event_icon_len)
3033
3034 for i in range(3):
3035 if "OK" not in dev[i].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
3036 raise Exception("REQ_HS20_ICON failed [2]")
3037 for i in range(3):
3038 ev = dev[i].wait_event(["RX-HS20-ICON"], timeout=5)
3039 if ev is None:
3040 raise Exception("Timeout on RX-HS20-ICON [2]")
3041
3042 if "FAIL" not in dev[2].request("DEL_HS20_ICON foo w1fi_logo"):
3043 raise Exception("Invalid DEL_HS20_ICON accepted")
3044 if "OK" not in dev[2].request("DEL_HS20_ICON " + bssid + " w1fi_logo"):
3045 raise Exception("DEL_HS20_ICON failed")
3046 if "OK" not in dev[1].request("DEL_HS20_ICON " + bssid):
3047 raise Exception("DEL_HS20_ICON failed")
3048 if "OK" not in dev[0].request("DEL_HS20_ICON "):
3049 raise Exception("DEL_HS20_ICON failed")
3050 for i in range(3):
3051 if "FAIL" not in dev[i].request("DEL_HS20_ICON "):
3052 raise Exception("DEL_HS20_ICON accepted when no icons left")
3053
3054 def test_ap_hs20_fetch_osu_no_info(dev, apdev):
3055 """Hotspot 2.0 OSU provider and no AP with info"""
3056 bssid = apdev[0]['bssid']
3057 params = hs20_ap_params()
3058 hostapd.add_ap(apdev[0], params)
3059
3060 dev[0].hs20_enable()
3061 dir = "/tmp/osu-fetch"
3062 if os.path.isdir(dir):
3063 files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
3064 for f in files:
3065 os.remove(dir + "/" + f)
3066 else:
3067 try:
3068 os.makedirs(dir)
3069 except:
3070 pass
3071 dev[0].scan_for_bss(bssid, freq="2412")
3072 try:
3073 dev[0].request("SET osu_dir " + dir)
3074 dev[0].request("FETCH_OSU")
3075 ev = dev[0].wait_event(["OSU provider fetch completed"], timeout=30)
3076 if ev is None:
3077 raise Exception("Timeout on OSU fetch")
3078 finally:
3079 files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
3080 for f in files:
3081 os.remove(dir + "/" + f)
3082 os.rmdir(dir)
3083
3084 def test_ap_hs20_fetch_osu_no_icon(dev, apdev):
3085 """Hotspot 2.0 OSU provider and no icon found"""
3086 bssid = apdev[0]['bssid']
3087 params = hs20_ap_params()
3088 params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo-no-file.png"
3089 params['osu_ssid'] = '"HS 2.0 OSU open"'
3090 params['osu_method_list'] = "1"
3091 params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
3092 params['osu_icon'] = "w1fi_logo"
3093 params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
3094 params['osu_server_uri'] = "https://example.com/osu/"
3095 hostapd.add_ap(apdev[0], params)
3096
3097 dev[0].hs20_enable()
3098 dir = "/tmp/osu-fetch"
3099 if os.path.isdir(dir):
3100 files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
3101 for f in files:
3102 os.remove(dir + "/" + f)
3103 else:
3104 try:
3105 os.makedirs(dir)
3106 except:
3107 pass
3108 dev[0].scan_for_bss(bssid, freq="2412")
3109 try:
3110 dev[0].request("SET osu_dir " + dir)
3111 dev[0].request("FETCH_OSU")
3112 ev = dev[0].wait_event(["OSU provider fetch completed"], timeout=30)
3113 if ev is None:
3114 raise Exception("Timeout on OSU fetch")
3115 finally:
3116 files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
3117 for f in files:
3118 os.remove(dir + "/" + f)
3119 os.rmdir(dir)
3120
3121 def test_ap_hs20_fetch_osu_single_ssid(dev, apdev):
3122 """Hotspot 2.0 OSU provider and single SSID"""
3123 bssid = apdev[0]['bssid']
3124 params = hs20_ap_params()
3125 params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo-no-file.png"
3126 params['osu_ssid'] = '"HS 2.0 OSU open"'
3127 params['osu_method_list'] = "1"
3128 params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
3129 params['osu_nai2'] = "osen@example.com"
3130 params['osu_icon'] = "w1fi_logo"
3131 params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
3132 params['osu_server_uri'] = "https://example.com/osu/"
3133 params['wpa_key_mgmt'] = "WPA-EAP OSEN"
3134 hostapd.add_ap(apdev[0], params)
3135
3136 dev[0].hs20_enable()
3137 dir = "/tmp/osu-fetch"
3138 if os.path.isdir(dir):
3139 files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
3140 for f in files:
3141 os.remove(dir + "/" + f)
3142 else:
3143 try:
3144 os.makedirs(dir)
3145 except:
3146 pass
3147 dev[0].scan_for_bss(bssid, freq="2412")
3148 try:
3149 dev[0].request("SET osu_dir " + dir)
3150 dev[0].request("FETCH_OSU")
3151 ev = dev[0].wait_event(["OSU provider fetch completed"], timeout=30)
3152 if ev is None:
3153 raise Exception("Timeout on OSU fetch")
3154 osu_ssid = False
3155 osu_ssid2 = False
3156 osu_nai = False
3157 osu_nai2 = False
3158 with open(os.path.join(dir, "osu-providers.txt"), "r") as f:
3159 for l in f.readlines():
3160 logger.info(l.strip())
3161 if l.strip() == "osu_ssid=HS 2.0 OSU open":
3162 osu_ssid = True
3163 if l.strip() == "osu_ssid2=test-hs20":
3164 osu_ssid2 = True
3165 if l.strip().startswith("osu_nai="):
3166 osu_nai = True
3167 if l.strip() == "osu_nai2=osen@example.com":
3168 osu_nai2 = True
3169 if not osu_ssid:
3170 raise Exception("osu_ssid not reported")
3171 if not osu_ssid2:
3172 raise Exception("osu_ssid2 not reported")
3173 if osu_nai:
3174 raise Exception("osu_nai reported unexpectedly")
3175 if not osu_nai2:
3176 raise Exception("osu_nai2 not reported")
3177 finally:
3178 files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
3179 for f in files:
3180 os.remove(dir + "/" + f)
3181 os.rmdir(dir)
3182
3183 def test_ap_hs20_fetch_osu_single_ssid2(dev, apdev):
3184 """Hotspot 2.0 OSU provider and single SSID (two OSU providers)"""
3185 bssid = apdev[0]['bssid']
3186 params = hs20_ap_params()
3187 params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo-no-file.png"
3188 params['osu_ssid'] = '"HS 2.0 OSU open"'
3189 params['osu_method_list'] = "1"
3190 params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
3191 params['osu_nai2'] = "osen@example.com"
3192 params['osu_icon'] = "w1fi_logo"
3193 params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
3194 params['osu_server_uri'] = "https://example.com/osu/"
3195 params['wpa_key_mgmt'] = "WPA-EAP OSEN"
3196 hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
3197
3198 hapd.set('osu_server_uri', 'https://another.example.com/osu/')
3199 hapd.set('osu_method_list', "1")
3200 hapd.set('osu_nai2', "osen@another.example.com")
3201 hapd.enable()
3202
3203 dev[0].hs20_enable()
3204 dir = "/tmp/osu-fetch"
3205 if os.path.isdir(dir):
3206 files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
3207 for f in files:
3208 os.remove(dir + "/" + f)
3209 else:
3210 try:
3211 os.makedirs(dir)
3212 except:
3213 pass
3214 dev[0].scan_for_bss(bssid, freq="2412")
3215 try:
3216 dev[0].request("SET osu_dir " + dir)
3217 dev[0].request("FETCH_OSU")
3218 ev = dev[0].wait_event(["OSU provider fetch completed"], timeout=30)
3219 if ev is None:
3220 raise Exception("Timeout on OSU fetch")
3221 osu_ssid = False
3222 osu_ssid2 = False
3223 osu_nai = False
3224 osu_nai2 = False
3225 osu_nai2b = False
3226 with open(os.path.join(dir, "osu-providers.txt"), "r") as f:
3227 for l in f.readlines():
3228 logger.info(l.strip())
3229 if l.strip() == "osu_ssid=HS 2.0 OSU open":
3230 osu_ssid = True
3231 if l.strip() == "osu_ssid2=test-hs20":
3232 osu_ssid2 = True
3233 if l.strip().startswith("osu_nai="):
3234 osu_nai = True
3235 if l.strip() == "osu_nai2=osen@example.com":
3236 osu_nai2 = True
3237 if l.strip() == "osu_nai2=osen@another.example.com":
3238 osu_nai2b = True
3239 if not osu_ssid:
3240 raise Exception("osu_ssid not reported")
3241 if not osu_ssid2:
3242 raise Exception("osu_ssid2 not reported")
3243 if osu_nai:
3244 raise Exception("osu_nai reported unexpectedly")
3245 if not osu_nai2:
3246 raise Exception("osu_nai2 not reported")
3247 if not osu_nai2b:
3248 raise Exception("osu_nai2b not reported")
3249 finally:
3250 files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
3251 for f in files:
3252 os.remove(dir + "/" + f)
3253 os.rmdir(dir)
3254
3255 def get_icon(dev, bssid, iconname):
3256 icon = ""
3257 pos = 0
3258 while True:
3259 if pos > 100000:
3260 raise Exception("Unexpectedly long icon")
3261 res = dev.request("GET_HS20_ICON " + bssid + " " + iconname + " %d 3000" % pos)
3262 if res.startswith("FAIL"):
3263 break
3264 icon += base64.b64decode(res)
3265 pos += 3000
3266 if len(icon) < 13:
3267 raise Exception("Too short GET_HS20_ICON response")
3268 return icon[0:13], icon[13:]
3269
3270 def test_ap_hs20_req_hs20_icon(dev, apdev):
3271 """Hotspot 2.0 OSU provider and multi-icon fetch with REQ_HS20_ICON"""
3272 bssid = apdev[0]['bssid']
3273 params = hs20_ap_params()
3274 params['hs20_icon'] = [ "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png",
3275 "128:80:zxx:image/png:test_logo:auth_serv/sha512-server.pem" ]
3276 params['osu_ssid'] = '"HS 2.0 OSU open"'
3277 params['osu_method_list'] = "1"
3278 params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
3279 params['osu_icon'] = [ "w1fi_logo", "w1fi_logo2" ]
3280 params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
3281 params['osu_server_uri'] = "https://example.com/osu/"
3282 hostapd.add_ap(apdev[0], params)
3283
3284 dev[0].scan_for_bss(bssid, freq="2412")
3285 run_req_hs20_icon(dev, bssid)
3286
3287 def run_req_hs20_icon(dev, bssid):
3288 # First, fetch two icons from the AP to wpa_supplicant
3289
3290 if "OK" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
3291 raise Exception("REQ_HS20_ICON failed")
3292 ev = dev[0].wait_event(["RX-HS20-ICON"], timeout=5)
3293 if ev is None:
3294 raise Exception("Timeout on RX-HS20-ICON (1)")
3295
3296 if "OK" not in dev[0].request("REQ_HS20_ICON " + bssid + " test_logo"):
3297 raise Exception("REQ_HS20_ICON failed")
3298 ev = dev[0].wait_event(["RX-HS20-ICON"], timeout=5)
3299 if ev is None:
3300 raise Exception("Timeout on RX-HS20-ICON (2)")
3301
3302 # Then, fetch the icons from wpa_supplicant for validation
3303
3304 hdr, data1 = get_icon(dev[0], bssid, "w1fi_logo")
3305 hdr, data2 = get_icon(dev[0], bssid, "test_logo")
3306
3307 with open('w1fi_logo.png', 'r') as f:
3308 data = f.read()
3309 if data1 != data:
3310 raise Exception("Unexpected icon data (1)")
3311
3312 with open('auth_serv/sha512-server.pem', 'r') as f:
3313 data = f.read()
3314 if data2 != data:
3315 raise Exception("Unexpected icon data (2)")
3316
3317 # Finally, delete the icons from wpa_supplicant
3318
3319 if "OK" not in dev[0].request("DEL_HS20_ICON " + bssid + " w1fi_logo"):
3320 raise Exception("DEL_HS20_ICON failed")
3321 if "OK" not in dev[0].request("DEL_HS20_ICON " + bssid + " test_logo"):
3322 raise Exception("DEL_HS20_ICON failed")
3323
3324 def test_ap_hs20_req_operator_icon(dev, apdev):
3325 """Hotspot 2.0 operator icons"""
3326 bssid = apdev[0]['bssid']
3327 params = hs20_ap_params()
3328 params['hs20_icon'] = [ "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png",
3329 "500:300:fi:image/png:test_logo:auth_serv/sha512-server.pem" ]
3330 params['operator_icon'] = [ "w1fi_logo", "unknown_logo", "test_logo" ]
3331 hostapd.add_ap(apdev[0], params)
3332
3333 value = struct.pack('<HH', 128, 80) + "zxx"
3334 value += struct.pack('B', 9) + "image/png"
3335 value += struct.pack('B', 9) + "w1fi_logo"
3336
3337 value += struct.pack('<HH', 500, 300) + "fi\0"
3338 value += struct.pack('B', 9) + "image/png"
3339 value += struct.pack('B', 9) + "test_logo"
3340
3341 dev[0].scan_for_bss(bssid, freq="2412")
3342
3343 if "OK" not in dev[0].request("ANQP_GET " + bssid + " hs20:12"):
3344 raise Exception("ANQP_GET command failed")
3345
3346 ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5)
3347 if ev is None:
3348 raise Exception("GAS query start timed out")
3349
3350 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
3351 if ev is None:
3352 raise Exception("GAS query timed out")
3353
3354 ev = dev[0].wait_event(["RX-HS20-ANQP"], timeout=1)
3355 if ev is None or "Operator Icon Metadata" not in ev:
3356 raise Exception("Did not receive Operator Icon Metadata")
3357
3358 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10)
3359 if ev is None:
3360 raise Exception("ANQP-QUERY-DONE event not seen")
3361 if "result=SUCCESS" not in ev:
3362 raise Exception("Unexpected result: " + ev)
3363
3364 bss = dev[0].get_bss(bssid)
3365 if "hs20_operator_icon_metadata" not in bss:
3366 raise Exception("hs20_operator_icon_metadata missing from BSS entry")
3367 if bss["hs20_operator_icon_metadata"] != binascii.hexlify(value):
3368 print binascii.hexlify(value)
3369 raise Exception("Unexpected hs20_operator_icon_metadata value: " +
3370 bss["hs20_operator_icon_metadata"])
3371
3372 run_req_hs20_icon(dev, bssid)
3373
3374 def test_ap_hs20_req_hs20_icon_oom(dev, apdev):
3375 """Hotspot 2.0 icon fetch OOM with REQ_HS20_ICON"""
3376 bssid = apdev[0]['bssid']
3377 params = hs20_ap_params()
3378 params['hs20_icon'] = [ "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png",
3379 "128:80:zxx:image/png:test_logo:auth_serv/sha512-server.pem" ]
3380 params['osu_ssid'] = '"HS 2.0 OSU open"'
3381 params['osu_method_list'] = "1"
3382 params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
3383 params['osu_icon'] = [ "w1fi_logo", "w1fi_logo2" ]
3384 params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
3385 params['osu_server_uri'] = "https://example.com/osu/"
3386 hostapd.add_ap(apdev[0], params)
3387
3388 dev[0].scan_for_bss(bssid, freq="2412")
3389
3390 if "FAIL" not in dev[0].request("REQ_HS20_ICON 11:22:33:44:55:66 w1fi_logo"):
3391 raise Exception("REQ_HS20_ICON succeeded with unknown BSSID")
3392
3393 with alloc_fail(dev[0], 1, "hs20_build_anqp_req;hs20_anqp_send_req"):
3394 if "FAIL" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
3395 raise Exception("REQ_HS20_ICON succeeded during OOM")
3396
3397 with alloc_fail(dev[0], 1, "gas_query_req;hs20_anqp_send_req"):
3398 if "FAIL" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
3399 raise Exception("REQ_HS20_ICON succeeded during OOM")
3400
3401 with alloc_fail(dev[0], 1, "=hs20_anqp_send_req"):
3402 if "FAIL" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
3403 raise Exception("REQ_HS20_ICON succeeded during OOM")
3404 with alloc_fail(dev[0], 2, "=hs20_anqp_send_req"):
3405 if "FAIL" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
3406 raise Exception("REQ_HS20_ICON succeeded during OOM")
3407
3408 if "OK" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
3409 raise Exception("REQ_HS20_ICON failed")
3410 ev = dev[0].wait_event(["RX-HS20-ICON"], timeout=5)
3411 if ev is None:
3412 raise Exception("Timeout on RX-HS20-ICON (1)")
3413
3414 with alloc_fail(dev[0], 1, "hs20_get_icon"):
3415 if "FAIL" not in dev[0].request("GET_HS20_ICON " + bssid + "w1fi_logo 0 100"):
3416 raise Exception("GET_HS20_ICON succeeded during OOM")
3417
3418 if "OK" not in dev[0].request("DEL_HS20_ICON " + bssid + " w1fi_logo"):
3419 raise Exception("DEL_HS20_ICON failed")
3420
3421 with alloc_fail(dev[0], 1, "=hs20_process_icon_binary_file"):
3422 if "OK" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
3423 raise Exception("REQ_HS20_ICON failed")
3424 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
3425
3426 def test_ap_hs20_req_hs20_icon_parallel(dev, apdev):
3427 """Hotspot 2.0 OSU provider and multi-icon parallel fetch with REQ_HS20_ICON"""
3428 bssid = apdev[0]['bssid']
3429 params = hs20_ap_params()
3430 params['hs20_icon'] = [ "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png",
3431 "128:80:zxx:image/png:test_logo:auth_serv/sha512-server.pem" ]
3432 params['osu_ssid'] = '"HS 2.0 OSU open"'
3433 params['osu_method_list'] = "1"
3434 params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
3435 params['osu_icon'] = [ "w1fi_logo", "w1fi_logo2" ]
3436 params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
3437 params['osu_server_uri'] = "https://example.com/osu/"
3438 hostapd.add_ap(apdev[0], params)
3439
3440 dev[0].scan_for_bss(bssid, freq="2412")
3441
3442 # First, fetch two icons from the AP to wpa_supplicant
3443
3444 if "OK" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
3445 raise Exception("REQ_HS20_ICON failed")
3446
3447 if "OK" not in dev[0].request("REQ_HS20_ICON " + bssid + " test_logo"):
3448 raise Exception("REQ_HS20_ICON failed")
3449 ev = dev[0].wait_event(["RX-HS20-ICON"], timeout=5)
3450 if ev is None:
3451 raise Exception("Timeout on RX-HS20-ICON (1)")
3452 ev = dev[0].wait_event(["RX-HS20-ICON"], timeout=5)
3453 if ev is None:
3454 raise Exception("Timeout on RX-HS20-ICON (2)")
3455
3456 # Then, fetch the icons from wpa_supplicant for validation
3457
3458 hdr, data1 = get_icon(dev[0], bssid, "w1fi_logo")
3459 hdr, data2 = get_icon(dev[0], bssid, "test_logo")
3460
3461 with open('w1fi_logo.png', 'r') as f:
3462 data = f.read()
3463 if data1 != data:
3464 raise Exception("Unexpected icon data (1)")
3465
3466 with open('auth_serv/sha512-server.pem', 'r') as f:
3467 data = f.read()
3468 if data2 != data:
3469 raise Exception("Unexpected icon data (2)")
3470
3471 # Finally, delete the icons from wpa_supplicant
3472
3473 if "OK" not in dev[0].request("DEL_HS20_ICON " + bssid + " w1fi_logo"):
3474 raise Exception("DEL_HS20_ICON failed")
3475 if "OK" not in dev[0].request("DEL_HS20_ICON " + bssid + " test_logo"):
3476 raise Exception("DEL_HS20_ICON failed")
3477
3478 def test_ap_hs20_fetch_osu_stop(dev, apdev):
3479 """Hotspot 2.0 OSU provider fetch stopped"""
3480 bssid = apdev[0]['bssid']
3481 params = hs20_ap_params()
3482 params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
3483 params['osu_ssid'] = '"HS 2.0 OSU open"'
3484 params['osu_method_list'] = "1"
3485 params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
3486 params['osu_icon'] = "w1fi_logo"
3487 params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
3488 params['osu_server_uri'] = "https://example.com/osu/"
3489 hapd = hostapd.add_ap(apdev[0], params)
3490
3491 dev[0].hs20_enable()
3492 dir = "/tmp/osu-fetch"
3493 if os.path.isdir(dir):
3494 files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
3495 for f in files:
3496 os.remove(dir + "/" + f)
3497 else:
3498 try:
3499 os.makedirs(dir)
3500 except:
3501 pass
3502 try:
3503 dev[0].request("SET osu_dir " + dir)
3504 dev[0].request("SCAN freq=2412-2462")
3505 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=10)
3506 if ev is None:
3507 raise Exception("Scan did not start")
3508 if "FAIL" not in dev[0].request("FETCH_OSU"):
3509 raise Exception("FETCH_OSU accepted while scanning")
3510 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 10)
3511 if ev is None:
3512 raise Exception("Scan timed out")
3513 hapd.set("ext_mgmt_frame_handling", "1")
3514 dev[0].request("FETCH_ANQP")
3515 if "FAIL" not in dev[0].request("FETCH_OSU"):
3516 raise Exception("FETCH_OSU accepted while in FETCH_ANQP")
3517 dev[0].request("STOP_FETCH_ANQP")
3518 dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5)
3519 dev[0].dump_monitor()
3520 hapd.dump_monitor()
3521 dev[0].request("INTERWORKING_SELECT freq=2412")
3522 for i in range(5):
3523 msg = hapd.mgmt_rx()
3524 if msg['subtype'] == 13:
3525 break
3526 if "FAIL" not in dev[0].request("FETCH_OSU"):
3527 raise Exception("FETCH_OSU accepted while in INTERWORKING_SELECT")
3528 ev = dev[0].wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH"],
3529 timeout=15)
3530 if ev is None:
3531 raise Exception("Network selection timed out")
3532
3533 dev[0].dump_monitor()
3534 if "OK" not in dev[0].request("FETCH_OSU"):
3535 raise Exception("FETCH_OSU failed")
3536 dev[0].request("CANCEL_FETCH_OSU")
3537
3538 for i in range(15):
3539 time.sleep(0.5)
3540 if dev[0].get_driver_status_field("scan_state") == "SCAN_COMPLETED":
3541 break
3542
3543 dev[0].dump_monitor()
3544 if "OK" not in dev[0].request("FETCH_OSU"):
3545 raise Exception("FETCH_OSU failed")
3546 if "FAIL" not in dev[0].request("FETCH_OSU"):
3547 raise Exception("FETCH_OSU accepted while in FETCH_OSU")
3548 ev = dev[0].wait_event(["GAS-QUERY-START"], 10)
3549 if ev is None:
3550 raise Exception("GAS timed out")
3551 if "FAIL" not in dev[0].request("FETCH_OSU"):
3552 raise Exception("FETCH_OSU accepted while in FETCH_OSU")
3553 dev[0].request("CANCEL_FETCH_OSU")
3554 ev = dev[0].wait_event(["GAS-QUERY-DONE"], 10)
3555 if ev is None:
3556 raise Exception("GAS event timed out after CANCEL_FETCH_OSU")
3557 finally:
3558 files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
3559 for f in files:
3560 os.remove(dir + "/" + f)
3561 os.rmdir(dir)
3562
3563 def test_ap_hs20_fetch_osu_proto(dev, apdev):
3564 """Hotspot 2.0 OSU provider and protocol testing"""
3565 bssid = apdev[0]['bssid']
3566 params = hs20_ap_params()
3567 hapd = hostapd.add_ap(apdev[0], params)
3568
3569 dev[0].hs20_enable()
3570 dir = "/tmp/osu-fetch"
3571 if os.path.isdir(dir):
3572 files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
3573 for f in files:
3574 os.remove(dir + "/" + f)
3575 else:
3576 try:
3577 os.makedirs(dir)
3578 except:
3579 pass
3580
3581 tests = [ ( "Empty provider list (no OSU SSID field)", '' ),
3582 ( "HS 2.0: Not enough room for OSU SSID",
3583 binascii.unhexlify('01') ),
3584 ( "HS 2.0: Invalid OSU SSID Length 33",
3585 binascii.unhexlify('21') + 33*'A' ),
3586 ( "HS 2.0: Not enough room for Number of OSU Providers",
3587 binascii.unhexlify('0130') ),
3588 ( "Truncated OSU Provider",
3589 binascii.unhexlify('013001020000') ),
3590 ( "HS 2.0: Ignored 5 bytes of extra data after OSU Providers",
3591 binascii.unhexlify('0130001122334455') ),
3592 ( "HS 2.0: Not enough room for OSU Friendly Name Length",
3593 binascii.unhexlify('013001000000') ),
3594 ( "HS 2.0: Not enough room for OSU Friendly Name Duples",
3595 build_prov('0100') ),
3596 ( "Invalid OSU Friendly Name", build_prov('040000000000') ),
3597 ( "Invalid OSU Friendly Name(2)", build_prov('040004000000') ),
3598 ( "HS 2.0: Not enough room for OSU Server URI length",
3599 build_prov('0000') ),
3600 ( "HS 2.0: Not enough room for OSU Server URI",
3601 build_prov('000001') ),
3602 ( "HS 2.0: Not enough room for OSU Method list length",
3603 build_prov('000000') ),
3604 ( "HS 2.0: Not enough room for OSU Method list",
3605 build_prov('00000001') ),
3606 ( "HS 2.0: Not enough room for Icons Available Length",
3607 build_prov('00000000') ),
3608 ( "HS 2.0: Not enough room for Icons Available Length(2)",
3609 build_prov('00000001ff00') ),
3610 ( "HS 2.0: Not enough room for Icons Available",
3611 build_prov('000000000100') ),
3612 ( "HS 2.0: Invalid Icon Metadata",
3613 build_prov('00000000010000') ),
3614 ( "HS 2.0: Not room for Icon Type",
3615 build_prov('000000000900111122223333330200') ),
3616 ( "HS 2.0: Not room for Icon Filename length",
3617 build_prov('000000000900111122223333330100') ),
3618 ( "HS 2.0: Not room for Icon Filename",
3619 build_prov('000000000900111122223333330001') ),
3620 ( "HS 2.0: Not enough room for OSU_NAI",
3621 build_prov('000000000000') ),
3622 ( "HS 2.0: Not enough room for OSU_NAI(2)",
3623 build_prov('00000000000001') ),
3624 ( "HS 2.0: Not enough room for OSU Service Description Length",
3625 build_prov('00000000000000') ),
3626 ( "HS 2.0: Not enough room for OSU Service Description Length(2)",
3627 build_prov('0000000000000000') ),
3628 ( "HS 2.0: Not enough room for OSU Service Description Duples",
3629 build_prov('000000000000000100') ),
3630 ( "Invalid OSU Service Description",
3631 build_prov('00000000000000040000000000') ),
3632 ( "Invalid OSU Service Description(2)",
3633 build_prov('00000000000000040004000000') ) ]
3634
3635 try:
3636 dev[0].request("SET osu_dir " + dir)
3637 run_fetch_osu_icon_failure(hapd, dev, bssid)
3638 for note, prov in tests:
3639 run_fetch_osu(hapd, dev, bssid, note, prov)
3640 finally:
3641 files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
3642 for f in files:
3643 os.remove(dir + "/" + f)
3644 os.rmdir(dir)
3645
3646 def test_ap_hs20_fetch_osu_invalid_dir(dev, apdev):
3647 """Hotspot 2.0 OSU provider and invalid directory"""
3648 bssid = apdev[0]['bssid']
3649 params = hs20_ap_params()
3650 params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
3651 params['osu_ssid'] = '"HS 2.0 OSU open"'
3652 params['osu_method_list'] = "1"
3653 params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
3654 params['osu_icon'] = "w1fi_logo"
3655 params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
3656 params['osu_server_uri'] = "https://example.com/osu/"
3657 hostapd.add_ap(apdev[0], params)
3658
3659 dev[0].hs20_enable()
3660 dir = "/tmp/osu-fetch-no-such-dir"
3661 dev[0].scan_for_bss(bssid, freq="2412")
3662 dev[0].request("SET osu_dir " + dir)
3663 dev[0].request("FETCH_OSU no-scan")
3664 ev = dev[0].wait_event(["Could not write OSU provider information"],
3665 timeout=15)
3666 if ev is None:
3667 raise Exception("Timeout on OSU fetch")
3668
3669 def test_ap_hs20_fetch_osu_oom(dev, apdev):
3670 """Hotspot 2.0 OSU provider and OOM"""
3671 bssid = apdev[0]['bssid']
3672 params = hs20_ap_params()
3673 params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
3674 params['osu_ssid'] = '"HS 2.0 OSU open"'
3675 params['osu_method_list'] = "1"
3676 params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
3677 params['osu_icon'] = "w1fi_logo"
3678 params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
3679 params['osu_server_uri'] = "https://example.com/osu/"
3680 hostapd.add_ap(apdev[0], params)
3681
3682 dev[0].hs20_enable()
3683 dir = "/tmp/osu-fetch"
3684 if os.path.isdir(dir):
3685 files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
3686 for f in files:
3687 os.remove(dir + "/" + f)
3688 else:
3689 try:
3690 os.makedirs(dir)
3691 except:
3692 pass
3693 dev[0].scan_for_bss(bssid, freq="2412")
3694 try:
3695 dev[0].request("SET osu_dir " + dir)
3696 with alloc_fail(dev[0], 1, "=hs20_osu_add_prov"):
3697 dev[0].request("FETCH_OSU no-scan")
3698 ev = dev[0].wait_event(["OSU provider fetch completed"], timeout=30)
3699 if ev is None:
3700 raise Exception("Timeout on OSU fetch")
3701 with alloc_fail(dev[0], 1, "hs20_anqp_send_req;hs20_next_osu_icon"):
3702 dev[0].request("FETCH_OSU no-scan")
3703 ev = dev[0].wait_event(["OSU provider fetch completed"], timeout=30)
3704 if ev is None:
3705 raise Exception("Timeout on OSU fetch")
3706 finally:
3707 files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
3708 for f in files:
3709 os.remove(dir + "/" + f)
3710 os.rmdir(dir)
3711
3712 def build_prov(prov):
3713 data = binascii.unhexlify(prov)
3714 return binascii.unhexlify('013001') + struct.pack('<H', len(data)) + data
3715
3716 def handle_osu_prov_fetch(hapd, dev, prov):
3717 # GAS/ANQP query for OSU Providers List
3718 query = gas_rx(hapd)
3719 gas = parse_gas(query['payload'])
3720 dialog_token = gas['dialog_token']
3721
3722 resp = action_response(query)
3723 osu_prov = struct.pack('<HH', 0xdddd, len(prov) + 6) + binascii.unhexlify('506f9a110800') + prov
3724 data = struct.pack('<H', len(osu_prov)) + osu_prov
3725 resp['payload'] = anqp_initial_resp(dialog_token, 0) + data
3726 send_gas_resp(hapd, resp)
3727
3728 ev = dev[0].wait_event(["RX-HS20-ANQP"], timeout=5)
3729 if ev is None:
3730 raise Exception("ANQP query response for OSU Providers not received")
3731 if "OSU Providers list" not in ev:
3732 raise Exception("ANQP query response for OSU Providers not received(2)")
3733 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
3734 if ev is None:
3735 raise Exception("ANQP query for OSU Providers list not completed")
3736
3737 def start_osu_fetch(hapd, dev, bssid, note):
3738 hapd.set("ext_mgmt_frame_handling", "0")
3739 dev[0].request("BSS_FLUSH 0")
3740 dev[0].scan_for_bss(bssid, freq="2412")
3741 hapd.set("ext_mgmt_frame_handling", "1")
3742 dev[0].dump_monitor()
3743 dev[0].request("NOTE " + note)
3744 dev[0].request("FETCH_OSU no-scan")
3745
3746 def wait_osu_fetch_completed(dev):
3747 ev = dev[0].wait_event(["OSU provider fetch completed"], timeout=5)
3748 if ev is None:
3749 raise Exception("Timeout on OSU fetch")
3750
3751 def run_fetch_osu_icon_failure(hapd, dev, bssid):
3752 start_osu_fetch(hapd, dev, bssid, "Icon fetch failure")
3753
3754 prov = binascii.unhexlify('01ff' + '01' + '800019000b656e6754657374204f53550c66696e54657374692d4f53551868747470733a2f2f6578616d706c652e636f6d2f6f73752f01011b00800050007a787809696d6167652f706e6709773166695f6c6f676f002a0013656e674578616d706c652073657276696365731566696e4573696d65726b6b6970616c76656c756a61')
3755 handle_osu_prov_fetch(hapd, dev, prov)
3756
3757 # GAS/ANQP query for icon
3758 query = gas_rx(hapd)
3759 gas = parse_gas(query['payload'])
3760 dialog_token = gas['dialog_token']
3761
3762 resp = action_response(query)
3763 # Unexpected Advertisement Protocol in response
3764 adv_proto = struct.pack('8B', 108, 6, 127, 0xdd, 0x00, 0x11, 0x22, 0x33)
3765 data = struct.pack('<H', 0)
3766 resp['payload'] = struct.pack('<BBBHH', ACTION_CATEG_PUBLIC,
3767 GAS_INITIAL_RESPONSE,
3768 gas['dialog_token'], 0, 0) + adv_proto + data
3769 send_gas_resp(hapd, resp)
3770
3771 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
3772 if ev is None:
3773 raise Exception("ANQP query for icon not completed")
3774
3775 wait_osu_fetch_completed(dev)
3776
3777 def run_fetch_osu(hapd, dev, bssid, note, prov):
3778 start_osu_fetch(hapd, dev, bssid, note)
3779 handle_osu_prov_fetch(hapd, dev, prov)
3780 wait_osu_fetch_completed(dev)
3781
3782 def test_ap_hs20_ft(dev, apdev):
3783 """Hotspot 2.0 connection with FT"""
3784 check_eap_capa(dev[0], "MSCHAPV2")
3785 bssid = apdev[0]['bssid']
3786 params = hs20_ap_params()
3787 params['wpa_key_mgmt'] = "FT-EAP"
3788 params['nas_identifier'] = "nas1.w1.fi"
3789 params['r1_key_holder'] = "000102030405"
3790 params["mobility_domain"] = "a1b2"
3791 params["reassociation_deadline"] = "1000"
3792 hapd = hostapd.add_ap(apdev[0], params)
3793
3794 dev[0].hs20_enable()
3795 id = dev[0].add_cred_values({ 'realm': "example.com",
3796 'username': "hs20-test",
3797 'password': "password",
3798 'ca_cert': "auth_serv/ca.pem",
3799 'domain': "example.com",
3800 'update_identifier': "1234" })
3801 interworking_select(dev[0], bssid, "home", freq="2412")
3802 interworking_connect(dev[0], bssid, "TTLS")
3803 dev[0].dump_monitor()
3804 key_mgmt = dev[0].get_status_field("key_mgmt")
3805 if key_mgmt != "FT-EAP":
3806 raise Exception("Unexpected key_mgmt: " + key_mgmt)
3807 # speed up testing by avoiding unnecessary scanning of other channels
3808 nid = dev[0].get_status_field("id")
3809 dev[0].set_network(nid, "scan_freq", "2412")
3810
3811 params = hs20_ap_params()
3812 hapd2 = hostapd.add_ap(apdev[1], params)
3813
3814 hapd.disable()
3815 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=10)
3816 if ev is None:
3817 raise Exception("Disconnection not reported")
3818 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=5)
3819 if ev is None:
3820 raise Exception("Connection to AP2 not reported")
3821 key_mgmt = dev[0].get_status_field("key_mgmt")
3822 if key_mgmt != "WPA2/IEEE 802.1X/EAP":
3823 raise Exception("Unexpected key_mgmt: " + key_mgmt)
3824
3825 def test_ap_hs20_remediation_sql(dev, apdev, params):
3826 """Hotspot 2.0 connection and remediation required using SQLite for user DB"""
3827 check_eap_capa(dev[0], "MSCHAPV2")
3828 try:
3829 import sqlite3
3830 except ImportError:
3831 raise HwsimSkip("No sqlite3 module available")
3832 dbfile = os.path.join(params['logdir'], "eap-user.db")
3833 try:
3834 os.remove(dbfile)
3835 except:
3836 pass
3837 con = sqlite3.connect(dbfile)
3838 with con:
3839 cur = con.cursor()
3840 cur.execute("CREATE TABLE users(identity TEXT PRIMARY KEY, methods TEXT, password TEXT, remediation TEXT, phase2 INTEGER)")
3841 cur.execute("CREATE TABLE wildcards(identity TEXT PRIMARY KEY, methods TEXT)")
3842 cur.execute("INSERT INTO users(identity,methods,password,phase2,remediation) VALUES ('user-mschapv2','TTLS-MSCHAPV2','password',1,'user')")
3843 cur.execute("INSERT INTO wildcards(identity,methods) VALUES ('','TTLS,TLS')")
3844 cur.execute("CREATE TABLE authlog(timestamp TEXT, session TEXT, nas_ip TEXT, username TEXT, note TEXT)")
3845
3846 try:
3847 params = { "ssid": "as", "beacon_int": "2000",
3848 "radius_server_clients": "auth_serv/radius_clients.conf",
3849 "radius_server_auth_port": '18128',
3850 "eap_server": "1",
3851 "eap_user_file": "sqlite:" + dbfile,
3852 "ca_cert": "auth_serv/ca.pem",
3853 "server_cert": "auth_serv/server.pem",
3854 "private_key": "auth_serv/server.key",
3855 "subscr_remediation_url": "https://example.org/",
3856 "subscr_remediation_method": "1" }
3857 hostapd.add_ap(apdev[1], params)
3858
3859 bssid = apdev[0]['bssid']
3860 params = hs20_ap_params()
3861 params['auth_server_port'] = "18128"
3862 hostapd.add_ap(apdev[0], params)
3863
3864 dev[0].request("SET pmf 1")
3865 dev[0].hs20_enable()
3866 id = dev[0].add_cred_values({ 'realm': "example.com",
3867 'username': "user-mschapv2",
3868 'password': "password",
3869 'ca_cert': "auth_serv/ca.pem" })
3870 interworking_select(dev[0], bssid, freq="2412")
3871 interworking_connect(dev[0], bssid, "TTLS")
3872 ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=5)
3873 if ev is None:
3874 raise Exception("Timeout on subscription remediation notice")
3875 if " 1 https://example.org/" not in ev:
3876 raise Exception("Unexpected subscription remediation event contents")
3877
3878 with con:
3879 cur = con.cursor()
3880 cur.execute("SELECT * from authlog")
3881 rows = cur.fetchall()
3882 if len(rows) < 1:
3883 raise Exception("No authlog entries")
3884
3885 finally:
3886 os.remove(dbfile)
3887 dev[0].request("SET pmf 0")
3888
3889 def test_ap_hs20_sim_provisioning(dev, apdev, params):
3890 """Hotspot 2.0 AAA server behavior for SIM provisioning"""
3891 check_eap_capa(dev[0], "SIM")
3892 try:
3893 import sqlite3
3894 except ImportError:
3895 raise HwsimSkip("No sqlite3 module available")
3896 dbfile = os.path.join(params['logdir'], "ap_hs20_sim_provisioning-eap-user.db")
3897 try:
3898 os.remove(dbfile)
3899 except:
3900 pass
3901 con = sqlite3.connect(dbfile)
3902 with con:
3903 cur = con.cursor()
3904 cur.execute("CREATE TABLE users(identity TEXT PRIMARY KEY, methods TEXT, password TEXT, remediation TEXT, phase2 INTEGER, last_msk TEXT)")
3905 cur.execute("CREATE TABLE wildcards(identity TEXT PRIMARY KEY, methods TEXT)")
3906 cur.execute("INSERT INTO wildcards(identity,methods) VALUES ('1','SIM')")
3907 cur.execute("CREATE TABLE authlog(timestamp TEXT, session TEXT, nas_ip TEXT, username TEXT, note TEXT)")
3908 cur.execute("CREATE TABLE current_sessions(mac_addr TEXT PRIMARY KEY, identity TEXT, start_time TEXT, nas TEXT, hs20_t_c_filtering BOOLEAN, waiting_coa_ack BOOLEAN, coa_ack_received BOOLEAN)")
3909
3910 try:
3911 params = { "ssid": "as", "beacon_int": "2000",
3912 "radius_server_clients": "auth_serv/radius_clients.conf",
3913 "radius_server_auth_port": '18128',
3914 "eap_server": "1",
3915 "eap_user_file": "sqlite:" + dbfile,
3916 "eap_sim_db": "unix:/tmp/hlr_auc_gw.sock",
3917 "ca_cert": "auth_serv/ca.pem",
3918 "server_cert": "auth_serv/server.pem",
3919 "private_key": "auth_serv/server.key",
3920 "hs20_sim_provisioning_url":
3921 "https://example.org/?hotspot2dot0-mobile-identifier-hash=",
3922 "subscr_remediation_method": "1" }
3923 hostapd.add_ap(apdev[1], params)
3924
3925 bssid = apdev[0]['bssid']
3926 params = hs20_ap_params()
3927 params['auth_server_port'] = "18128"
3928 hostapd.add_ap(apdev[0], params)
3929
3930 dev[0].request("SET pmf 1")
3931 dev[0].hs20_enable()
3932 dev[0].connect("test-hs20", proto="RSN", key_mgmt="WPA-EAP", eap="SIM",
3933 ieee80211w="1",
3934 identity="1232010000000000",
3935 password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
3936 scan_freq="2412", update_identifier="54321")
3937 ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=0.5)
3938 if ev is not None:
3939 raise Exception("Unexpected subscription remediation notice")
3940 dev[0].request("REMOVE_NETWORK all")
3941 dev[0].wait_disconnected()
3942 dev[0].dump_monitor()
3943
3944 dev[0].connect("test-hs20", proto="RSN", key_mgmt="WPA-EAP", eap="SIM",
3945 ieee80211w="1",
3946 identity="1232010000000000",
3947 password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
3948 scan_freq="2412", update_identifier="0")
3949 ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=5)
3950 if ev is None:
3951 raise Exception("Timeout on subscription remediation notice")
3952 if " 1 https://example.org/?hotspot2dot0-mobile-identifier-hash=" not in ev:
3953 raise Exception("Unexpected subscription remediation event contents: " + ev)
3954 id_hash = ev.split(' ')[2].split('=')[1]
3955
3956 with con:
3957 cur = con.cursor()
3958 cur.execute("SELECT * from authlog")
3959 rows = cur.fetchall()
3960 if len(rows) < 1:
3961 raise Exception("No authlog entries")
3962
3963 with con:
3964 cur = con.cursor()
3965 cur.execute("SELECT * from sim_provisioning")
3966 rows = cur.fetchall()
3967 if len(rows) != 1:
3968 raise Exeception("Unexpected number of rows in sim_provisioning (%d; expected %d)" % (len(rows), 1))
3969 logger.info("sim_provisioning: " + str(rows))
3970 if len(rows[0][0]) != 32:
3971 raise Exception("Unexpected mobile_identifier_hash length in DB")
3972 if rows[0][1] != "232010000000000":
3973 raise Exception("Unexpected IMSI in DB")
3974 if rows[0][2] != dev[0].own_addr():
3975 raise Exception("Unexpected MAC address in DB")
3976 if rows[0][0] != id_hash:
3977 raise Exception("hotspot2dot0-mobile-identifier-hash mismatch")
3978 finally:
3979 dev[0].request("SET pmf 0")
3980
3981 def test_ap_hs20_external_selection(dev, apdev):
3982 """Hotspot 2.0 connection using external network selection and creation"""
3983 check_eap_capa(dev[0], "MSCHAPV2")
3984 bssid = apdev[0]['bssid']
3985 params = hs20_ap_params()
3986 params['hessid'] = bssid
3987 params['disable_dgaf'] = '1'
3988 hostapd.add_ap(apdev[0], params)
3989
3990 dev[0].hs20_enable()
3991 dev[0].connect("test-hs20", proto="RSN", key_mgmt="WPA-EAP", eap="TTLS",
3992 ieee80211w="1",
3993 identity="hs20-test", password="password",
3994 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
3995 scan_freq="2412", update_identifier="54321",
3996 roaming_consortium_selection="1020304050")
3997 if dev[0].get_status_field("hs20") != "3":
3998 raise Exception("Unexpected hs20 indication")
3999 network_id = dev[0].get_status_field("id")
4000 sel = dev[0].get_network(network_id, "roaming_consortium_selection")
4001 if sel != "1020304050":
4002 raise Exception("Unexpected roaming_consortium_selection value: " + sel)
4003
4004 def test_ap_hs20_random_mac_addr(dev, apdev):
4005 """Hotspot 2.0 connection with random MAC address"""
4006 check_eap_capa(dev[0], "MSCHAPV2")
4007 bssid = apdev[0]['bssid']
4008 params = hs20_ap_params()
4009 params['hessid'] = bssid
4010 params['disable_dgaf'] = '1'
4011 hapd = hostapd.add_ap(apdev[0], params)
4012
4013 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
4014 wpas.interface_add("wlan5")
4015 addr = wpas.p2p_interface_addr()
4016 wpas.request("SET mac_addr 1")
4017 wpas.request("SET preassoc_mac_addr 1")
4018 wpas.request("SET rand_addr_lifetime 60")
4019 wpas.hs20_enable()
4020 wpas.flush_scan_cache()
4021 id = wpas.add_cred_values({ 'realm': "example.com",
4022 'username': "hs20-test",
4023 'password': "password",
4024 'ca_cert': "auth_serv/ca.pem",
4025 'domain': "example.com",
4026 'update_identifier': "1234" })
4027 interworking_select(wpas, bssid, "home", freq="2412")
4028 interworking_connect(wpas, bssid, "TTLS")
4029 addr1 = wpas.get_driver_status_field("addr")
4030 if addr == addr1:
4031 raise Exception("Did not use random MAC address")
4032
4033 sta = hapd.get_sta(addr)
4034 if sta['addr'] != "FAIL":
4035 raise Exception("Unexpected STA association with permanent address")
4036 sta = hapd.get_sta(addr1)
4037 if sta['addr'] != addr1:
4038 raise Exception("STA association with random address not found")
4039
4040 def test_ap_hs20_multi_network_and_cred_removal(dev, apdev):
4041 """Multiple networks and cred removal"""
4042 check_eap_capa(dev[0], "MSCHAPV2")
4043 bssid = apdev[0]['bssid']
4044 params = hs20_ap_params()
4045 params['nai_realm'] = [ "0,example.com,25[3:26]"]
4046 hapd = hostapd.add_ap(apdev[0], params)
4047
4048 dev[0].add_network()
4049 dev[0].hs20_enable()
4050 id = dev[0].add_cred_values({ 'realm': "example.com",
4051 'username': "user",
4052 'password': "password" })
4053 interworking_select(dev[0], bssid, freq="2412")
4054 interworking_connect(dev[0], bssid, "PEAP")
4055 dev[0].add_network()
4056
4057 dev[0].request("DISCONNECT")
4058 dev[0].wait_disconnected(timeout=10)
4059
4060 hapd.disable()
4061 hapd.set("ssid", "another ssid")
4062 hapd.enable()
4063
4064 interworking_select(dev[0], bssid, freq="2412")
4065 interworking_connect(dev[0], bssid, "PEAP")
4066 dev[0].add_network()
4067 if len(dev[0].list_networks()) != 5:
4068 raise Exception("Unexpected number of networks prior to remove_crec")
4069
4070 dev[0].dump_monitor()
4071 dev[0].remove_cred(id)
4072 if len(dev[0].list_networks()) != 3:
4073 raise Exception("Unexpected number of networks after to remove_crec")
4074 dev[0].wait_disconnected(timeout=10)
4075
4076 def test_ap_hs20_interworking_add_network(dev, apdev):
4077 """Hotspot 2.0 connection using INTERWORKING_ADD_NETWORK"""
4078 check_eap_capa(dev[0], "MSCHAPV2")
4079 bssid = apdev[0]['bssid']
4080 params = hs20_ap_params()
4081 params['nai_realm'] = [ "0,example.com,21[3:26][6:7][99:99]" ]
4082 hostapd.add_ap(apdev[0], params)
4083
4084 dev[0].hs20_enable()
4085 dev[0].add_cred_values(default_cred(user="user"))
4086 interworking_select(dev[0], bssid, freq=2412)
4087 id = dev[0].interworking_add_network(bssid)
4088 dev[0].select_network(id, freq=2412)
4089 dev[0].wait_connected()
4090
4091 def _test_ap_hs20_proxyarp(dev, apdev):
4092 bssid = apdev[0]['bssid']
4093 params = hs20_ap_params()
4094 params['hessid'] = bssid
4095 params['disable_dgaf'] = '0'
4096 params['proxy_arp'] = '1'
4097 hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
4098 if "OK" in hapd.request("ENABLE"):
4099 raise Exception("Incomplete hostapd configuration was accepted")
4100 hapd.set("ap_isolate", "1")
4101 if "OK" in hapd.request("ENABLE"):
4102 raise Exception("Incomplete hostapd configuration was accepted")
4103 hapd.set('bridge', 'ap-br0')
4104 hapd.dump_monitor()
4105 try:
4106 hapd.enable()
4107 except:
4108 # For now, do not report failures due to missing kernel support
4109 raise HwsimSkip("Could not start hostapd - assume proxyarp not supported in kernel version")
4110 ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=10)
4111 if ev is None:
4112 raise Exception("AP startup timed out")
4113 if "AP-ENABLED" not in ev:
4114 raise Exception("AP startup failed")
4115
4116 dev[0].hs20_enable()
4117 subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
4118 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
4119
4120 id = dev[0].add_cred_values({ 'realm': "example.com",
4121 'username': "hs20-test",
4122 'password': "password",
4123 'ca_cert': "auth_serv/ca.pem",
4124 'domain': "example.com",
4125 'update_identifier': "1234" })
4126 interworking_select(dev[0], bssid, "home", freq="2412")
4127 interworking_connect(dev[0], bssid, "TTLS")
4128
4129 dev[1].connect("test-hs20", key_mgmt="WPA-EAP", eap="TTLS",
4130 identity="hs20-test", password="password",
4131 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
4132 scan_freq="2412")
4133 time.sleep(0.1)
4134
4135 addr0 = dev[0].p2p_interface_addr()
4136 addr1 = dev[1].p2p_interface_addr()
4137
4138 src_ll_opt0 = "\x01\x01" + binascii.unhexlify(addr0.replace(':',''))
4139 src_ll_opt1 = "\x01\x01" + binascii.unhexlify(addr1.replace(':',''))
4140
4141 pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
4142 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2",
4143 opt=src_ll_opt0)
4144 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
4145 raise Exception("DATA_TEST_FRAME failed")
4146
4147 pkt = build_ns(src_ll=addr1, ip_src="aaaa:bbbb:dddd::2",
4148 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:dddd::2",
4149 opt=src_ll_opt1)
4150 if "OK" not in dev[1].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
4151 raise Exception("DATA_TEST_FRAME failed")
4152
4153 pkt = build_ns(src_ll=addr1, ip_src="aaaa:bbbb:eeee::2",
4154 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:eeee::2",
4155 opt=src_ll_opt1)
4156 if "OK" not in dev[1].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
4157 raise Exception("DATA_TEST_FRAME failed")
4158
4159 matches = get_permanent_neighbors("ap-br0")
4160 logger.info("After connect: " + str(matches))
4161 if len(matches) != 3:
4162 raise Exception("Unexpected number of neighbor entries after connect")
4163 if 'aaaa:bbbb:cccc::2 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
4164 raise Exception("dev0 addr missing")
4165 if 'aaaa:bbbb:dddd::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches:
4166 raise Exception("dev1 addr(1) missing")
4167 if 'aaaa:bbbb:eeee::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches:
4168 raise Exception("dev1 addr(2) missing")
4169 dev[0].request("DISCONNECT")
4170 dev[1].request("DISCONNECT")
4171 time.sleep(0.5)
4172 matches = get_permanent_neighbors("ap-br0")
4173 logger.info("After disconnect: " + str(matches))
4174 if len(matches) > 0:
4175 raise Exception("Unexpected neighbor entries after disconnect")
4176
4177 def test_ap_hs20_hidden_ssid_in_scan_res(dev, apdev):
4178 """Hotspot 2.0 connection with hidden SSId in scan results"""
4179 check_eap_capa(dev[0], "MSCHAPV2")
4180 bssid = apdev[0]['bssid']
4181
4182 hapd = hostapd.add_ap(apdev[0], { "ssid": 'secret',
4183 "ignore_broadcast_ssid": "1" })
4184 dev[0].scan_for_bss(bssid, freq=2412)
4185 hapd.disable()
4186 hapd_global = hostapd.HostapdGlobal(apdev[0])
4187 hapd_global.flush()
4188 hapd_global.remove(apdev[0]['ifname'])
4189
4190 params = hs20_ap_params()
4191 params['hessid'] = bssid
4192 hapd = hostapd.add_ap(apdev[0], params)
4193
4194 dev[0].hs20_enable()
4195 id = dev[0].add_cred_values({ 'realm': "example.com",
4196 'username': "hs20-test",
4197 'password': "password",
4198 'ca_cert': "auth_serv/ca.pem",
4199 'domain': "example.com" })
4200 interworking_select(dev[0], bssid, "home", freq="2412")
4201 interworking_connect(dev[0], bssid, "TTLS")
4202
4203 # clear BSS table to avoid issues in following test cases
4204 dev[0].request("DISCONNECT")
4205 dev[0].wait_disconnected()
4206 hapd.disable()
4207 dev[0].flush_scan_cache()
4208 dev[0].flush_scan_cache()
4209
4210 def test_ap_hs20_proxyarp(dev, apdev):
4211 """Hotspot 2.0 and ProxyARP"""
4212 check_eap_capa(dev[0], "MSCHAPV2")
4213 try:
4214 _test_ap_hs20_proxyarp(dev, apdev)
4215 finally:
4216 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
4217 stderr=open('/dev/null', 'w'))
4218 subprocess.call(['brctl', 'delbr', 'ap-br0'],
4219 stderr=open('/dev/null', 'w'))
4220
4221 def _test_ap_hs20_proxyarp_dgaf(dev, apdev, disabled):
4222 bssid = apdev[0]['bssid']
4223 params = hs20_ap_params()
4224 params['hessid'] = bssid
4225 params['disable_dgaf'] = '1' if disabled else '0'
4226 params['proxy_arp'] = '1'
4227 params['na_mcast_to_ucast'] = '1'
4228 params['ap_isolate'] = '1'
4229 params['bridge'] = 'ap-br0'
4230 hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
4231 try:
4232 hapd.enable()
4233 except:
4234 # For now, do not report failures due to missing kernel support
4235 raise HwsimSkip("Could not start hostapd - assume proxyarp not supported in kernel version")
4236 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
4237 if ev is None:
4238 raise Exception("AP startup timed out")
4239
4240 dev[0].hs20_enable()
4241 subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
4242 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
4243
4244 id = dev[0].add_cred_values({ 'realm': "example.com",
4245 'username': "hs20-test",
4246 'password': "password",
4247 'ca_cert': "auth_serv/ca.pem",
4248 'domain': "example.com",
4249 'update_identifier': "1234" })
4250 interworking_select(dev[0], bssid, "home", freq="2412")
4251 interworking_connect(dev[0], bssid, "TTLS")
4252
4253 dev[1].connect("test-hs20", key_mgmt="WPA-EAP", eap="TTLS",
4254 identity="hs20-test", password="password",
4255 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
4256 scan_freq="2412")
4257 time.sleep(0.1)
4258
4259 addr0 = dev[0].p2p_interface_addr()
4260
4261 src_ll_opt0 = "\x01\x01" + binascii.unhexlify(addr0.replace(':',''))
4262
4263 pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
4264 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2",
4265 opt=src_ll_opt0)
4266 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
4267 raise Exception("DATA_TEST_FRAME failed")
4268
4269 pkt = build_ra(src_ll=apdev[0]['bssid'], ip_src="aaaa:bbbb:cccc::33",
4270 ip_dst="ff01::1")
4271 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
4272 raise Exception("DATA_TEST_FRAME failed")
4273
4274 pkt = build_na(src_ll=apdev[0]['bssid'], ip_src="aaaa:bbbb:cccc::44",
4275 ip_dst="ff01::1", target="aaaa:bbbb:cccc::55")
4276 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
4277 raise Exception("DATA_TEST_FRAME failed")
4278
4279 pkt = build_dhcp_ack(dst_ll="ff:ff:ff:ff:ff:ff", src_ll=bssid,
4280 ip_src="192.168.1.1", ip_dst="255.255.255.255",
4281 yiaddr="192.168.1.123", chaddr=addr0)
4282 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
4283 raise Exception("DATA_TEST_FRAME failed")
4284 # another copy for additional code coverage
4285 pkt = build_dhcp_ack(dst_ll=addr0, src_ll=bssid,
4286 ip_src="192.168.1.1", ip_dst="255.255.255.255",
4287 yiaddr="192.168.1.123", chaddr=addr0)
4288 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
4289 raise Exception("DATA_TEST_FRAME failed")
4290
4291 matches = get_permanent_neighbors("ap-br0")
4292 logger.info("After connect: " + str(matches))
4293 if len(matches) != 2:
4294 raise Exception("Unexpected number of neighbor entries after connect")
4295 if 'aaaa:bbbb:cccc::2 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
4296 raise Exception("dev0 addr missing")
4297 if '192.168.1.123 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
4298 raise Exception("dev0 IPv4 addr missing")
4299 dev[0].request("DISCONNECT")
4300 dev[1].request("DISCONNECT")
4301 time.sleep(0.5)
4302 matches = get_permanent_neighbors("ap-br0")
4303 logger.info("After disconnect: " + str(matches))
4304 if len(matches) > 0:
4305 raise Exception("Unexpected neighbor entries after disconnect")
4306
4307 def test_ap_hs20_proxyarp_disable_dgaf(dev, apdev):
4308 """Hotspot 2.0 and ProxyARP with DGAF disabled"""
4309 check_eap_capa(dev[0], "MSCHAPV2")
4310 try:
4311 _test_ap_hs20_proxyarp_dgaf(dev, apdev, True)
4312 finally:
4313 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
4314 stderr=open('/dev/null', 'w'))
4315 subprocess.call(['brctl', 'delbr', 'ap-br0'],
4316 stderr=open('/dev/null', 'w'))
4317
4318 def test_ap_hs20_proxyarp_enable_dgaf(dev, apdev):
4319 """Hotspot 2.0 and ProxyARP with DGAF enabled"""
4320 check_eap_capa(dev[0], "MSCHAPV2")
4321 try:
4322 _test_ap_hs20_proxyarp_dgaf(dev, apdev, False)
4323 finally:
4324 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
4325 stderr=open('/dev/null', 'w'))
4326 subprocess.call(['brctl', 'delbr', 'ap-br0'],
4327 stderr=open('/dev/null', 'w'))
4328
4329 def ip_checksum(buf):
4330 sum = 0
4331 if len(buf) & 0x01:
4332 buf += '\x00'
4333 for i in range(0, len(buf), 2):
4334 val, = struct.unpack('H', buf[i:i+2])
4335 sum += val
4336 while (sum >> 16):
4337 sum = (sum & 0xffff) + (sum >> 16)
4338 return struct.pack('H', ~sum & 0xffff)
4339
4340 def ipv6_solicited_node_mcaddr(target):
4341 prefix = socket.inet_pton(socket.AF_INET6, "ff02::1:ff00:0")
4342 mask = socket.inet_pton(socket.AF_INET6, "::ff:ffff")
4343 _target = socket.inet_pton(socket.AF_INET6, target)
4344 p = struct.unpack('4I', prefix)
4345 m = struct.unpack('4I', mask)
4346 t = struct.unpack('4I', _target)
4347 res = (p[0] | (t[0] & m[0]),
4348 p[1] | (t[1] & m[1]),
4349 p[2] | (t[2] & m[2]),
4350 p[3] | (t[3] & m[3]))
4351 return socket.inet_ntop(socket.AF_INET6, struct.pack('4I', *res))
4352
4353 def build_icmpv6(ipv6_addrs, type, code, payload):
4354 start = struct.pack("BB", type, code)
4355 end = payload
4356 icmp = start + '\x00\x00' + end
4357 pseudo = ipv6_addrs + struct.pack(">LBBBB", len(icmp), 0, 0, 0, 58)
4358 csum = ip_checksum(pseudo + icmp)
4359 return start + csum + end
4360
4361 def build_ra(src_ll, ip_src, ip_dst, cur_hop_limit=0, router_lifetime=0,
4362 reachable_time=0, retrans_timer=0, opt=None):
4363 link_mc = binascii.unhexlify("3333ff000002")
4364 _src_ll = binascii.unhexlify(src_ll.replace(':',''))
4365 proto = '\x86\xdd'
4366 ehdr = link_mc + _src_ll + proto
4367 _ip_src = socket.inet_pton(socket.AF_INET6, ip_src)
4368 _ip_dst = socket.inet_pton(socket.AF_INET6, ip_dst)
4369
4370 adv = struct.pack('>BBHLL', cur_hop_limit, 0, router_lifetime,
4371 reachable_time, retrans_timer)
4372 if opt:
4373 payload = adv + opt
4374 else:
4375 payload = adv
4376 icmp = build_icmpv6(_ip_src + _ip_dst, 134, 0, payload)
4377
4378 ipv6 = struct.pack('>BBBBHBB', 0x60, 0, 0, 0, len(icmp), 58, 255)
4379 ipv6 += _ip_src + _ip_dst
4380
4381 return ehdr + ipv6 + icmp
4382
4383 def build_ns(src_ll, ip_src, ip_dst, target, opt=None):
4384 link_mc = binascii.unhexlify("3333ff000002")
4385 _src_ll = binascii.unhexlify(src_ll.replace(':',''))
4386 proto = '\x86\xdd'
4387 ehdr = link_mc + _src_ll + proto
4388 _ip_src = socket.inet_pton(socket.AF_INET6, ip_src)
4389 if ip_dst is None:
4390 ip_dst = ipv6_solicited_node_mcaddr(target)
4391 _ip_dst = socket.inet_pton(socket.AF_INET6, ip_dst)
4392
4393 reserved = '\x00\x00\x00\x00'
4394 _target = socket.inet_pton(socket.AF_INET6, target)
4395 if opt:
4396 payload = reserved + _target + opt
4397 else:
4398 payload = reserved + _target
4399 icmp = build_icmpv6(_ip_src + _ip_dst, 135, 0, payload)
4400
4401 ipv6 = struct.pack('>BBBBHBB', 0x60, 0, 0, 0, len(icmp), 58, 255)
4402 ipv6 += _ip_src + _ip_dst
4403
4404 return ehdr + ipv6 + icmp
4405
4406 def send_ns(dev, src_ll=None, target=None, ip_src=None, ip_dst=None, opt=None,
4407 hapd_bssid=None):
4408 if hapd_bssid:
4409 if src_ll is None:
4410 src_ll = hapd_bssid
4411 cmd = "DATA_TEST_FRAME ifname=ap-br0 "
4412 else:
4413 if src_ll is None:
4414 src_ll = dev.p2p_interface_addr()
4415 cmd = "DATA_TEST_FRAME "
4416
4417 if opt is None:
4418 opt = "\x01\x01" + binascii.unhexlify(src_ll.replace(':',''))
4419
4420 pkt = build_ns(src_ll=src_ll, ip_src=ip_src, ip_dst=ip_dst, target=target,
4421 opt=opt)
4422 if "OK" not in dev.request(cmd + binascii.hexlify(pkt)):
4423 raise Exception("DATA_TEST_FRAME failed")
4424
4425 def build_na(src_ll, ip_src, ip_dst, target, opt=None, flags=0):
4426 link_mc = binascii.unhexlify("3333ff000002")
4427 _src_ll = binascii.unhexlify(src_ll.replace(':',''))
4428 proto = '\x86\xdd'
4429 ehdr = link_mc + _src_ll + proto
4430 _ip_src = socket.inet_pton(socket.AF_INET6, ip_src)
4431 _ip_dst = socket.inet_pton(socket.AF_INET6, ip_dst)
4432
4433 _target = socket.inet_pton(socket.AF_INET6, target)
4434 if opt:
4435 payload = struct.pack('>Bxxx', flags) + _target + opt
4436 else:
4437 payload = struct.pack('>Bxxx', flags) + _target
4438 icmp = build_icmpv6(_ip_src + _ip_dst, 136, 0, payload)
4439
4440 ipv6 = struct.pack('>BBBBHBB', 0x60, 0, 0, 0, len(icmp), 58, 255)
4441 ipv6 += _ip_src + _ip_dst
4442
4443 return ehdr + ipv6 + icmp
4444
4445 def send_na(dev, src_ll=None, target=None, ip_src=None, ip_dst=None, opt=None,
4446 hapd_bssid=None):
4447 if hapd_bssid:
4448 if src_ll is None:
4449 src_ll = hapd_bssid
4450 cmd = "DATA_TEST_FRAME ifname=ap-br0 "
4451 else:
4452 if src_ll is None:
4453 src_ll = dev.p2p_interface_addr()
4454 cmd = "DATA_TEST_FRAME "
4455
4456 pkt = build_na(src_ll=src_ll, ip_src=ip_src, ip_dst=ip_dst, target=target,
4457 opt=opt)
4458 if "OK" not in dev.request(cmd + binascii.hexlify(pkt)):
4459 raise Exception("DATA_TEST_FRAME failed")
4460
4461 def build_dhcp_ack(dst_ll, src_ll, ip_src, ip_dst, yiaddr, chaddr,
4462 subnet_mask="255.255.255.0", truncated_opt=False,
4463 wrong_magic=False, force_tot_len=None, no_dhcp=False,
4464 udp_checksum=True):
4465 _dst_ll = binascii.unhexlify(dst_ll.replace(':',''))
4466 _src_ll = binascii.unhexlify(src_ll.replace(':',''))
4467 proto = '\x08\x00'
4468 ehdr = _dst_ll + _src_ll + proto
4469 _ip_src = socket.inet_pton(socket.AF_INET, ip_src)
4470 _ip_dst = socket.inet_pton(socket.AF_INET, ip_dst)
4471 _subnet_mask = socket.inet_pton(socket.AF_INET, subnet_mask)
4472
4473 _ciaddr = '\x00\x00\x00\x00'
4474 _yiaddr = socket.inet_pton(socket.AF_INET, yiaddr)
4475 _siaddr = '\x00\x00\x00\x00'
4476 _giaddr = '\x00\x00\x00\x00'
4477 _chaddr = binascii.unhexlify(chaddr.replace(':','') + "00000000000000000000")
4478 payload = struct.pack('>BBBBL3BB', 2, 1, 6, 0, 12345, 0, 0, 0, 0)
4479 payload += _ciaddr + _yiaddr + _siaddr + _giaddr + _chaddr + 192*'\x00'
4480 # magic
4481 if wrong_magic:
4482 payload += '\x63\x82\x53\x00'
4483 else:
4484 payload += '\x63\x82\x53\x63'
4485 if truncated_opt:
4486 payload += '\x22\xff\x00'
4487 # Option: DHCP Message Type = ACK
4488 payload += '\x35\x01\x05'
4489 # Pad Option
4490 payload += '\x00'
4491 # Option: Subnet Mask
4492 payload += '\x01\x04' + _subnet_mask
4493 # Option: Time Offset
4494 payload += struct.pack('>BBL', 2, 4, 0)
4495 # End Option
4496 payload += '\xff'
4497 # Pad Option
4498 payload += '\x00\x00\x00\x00'
4499
4500 if no_dhcp:
4501 payload = struct.pack('>BBBBL3BB', 2, 1, 6, 0, 12345, 0, 0, 0, 0)
4502 payload += _ciaddr + _yiaddr + _siaddr + _giaddr + _chaddr + 192*'\x00'
4503
4504 if udp_checksum:
4505 pseudohdr = _ip_src + _ip_dst + struct.pack('>BBH', 0, 17,
4506 8 + len(payload))
4507 udphdr = struct.pack('>HHHH', 67, 68, 8 + len(payload), 0)
4508 checksum, = struct.unpack('>H', ip_checksum(pseudohdr + udphdr + payload))
4509 else:
4510 checksum = 0
4511 udp = struct.pack('>HHHH', 67, 68, 8 + len(payload), checksum) + payload
4512
4513 if force_tot_len:
4514 tot_len = force_tot_len
4515 else:
4516 tot_len = 20 + len(udp)
4517 start = struct.pack('>BBHHBBBB', 0x45, 0, tot_len, 0, 0, 0, 128, 17)
4518 ipv4 = start + '\x00\x00' + _ip_src + _ip_dst
4519 csum = ip_checksum(ipv4)
4520 ipv4 = start + csum + _ip_src + _ip_dst
4521
4522 return ehdr + ipv4 + udp
4523
4524 def build_arp(dst_ll, src_ll, opcode, sender_mac, sender_ip,
4525 target_mac, target_ip):
4526 _dst_ll = binascii.unhexlify(dst_ll.replace(':',''))
4527 _src_ll = binascii.unhexlify(src_ll.replace(':',''))
4528 proto = '\x08\x06'
4529 ehdr = _dst_ll + _src_ll + proto
4530
4531 _sender_mac = binascii.unhexlify(sender_mac.replace(':',''))
4532 _sender_ip = socket.inet_pton(socket.AF_INET, sender_ip)
4533 _target_mac = binascii.unhexlify(target_mac.replace(':',''))
4534 _target_ip = socket.inet_pton(socket.AF_INET, target_ip)
4535
4536 arp = struct.pack('>HHBBH', 1, 0x0800, 6, 4, opcode)
4537 arp += _sender_mac + _sender_ip
4538 arp += _target_mac + _target_ip
4539
4540 return ehdr + arp
4541
4542 def send_arp(dev, dst_ll="ff:ff:ff:ff:ff:ff", src_ll=None, opcode=1,
4543 sender_mac=None, sender_ip="0.0.0.0",
4544 target_mac="00:00:00:00:00:00", target_ip="0.0.0.0",
4545 hapd_bssid=None):
4546 if hapd_bssid:
4547 if src_ll is None:
4548 src_ll = hapd_bssid
4549 if sender_mac is None:
4550 sender_mac = hapd_bssid
4551 cmd = "DATA_TEST_FRAME ifname=ap-br0 "
4552 else:
4553 if src_ll is None:
4554 src_ll = dev.p2p_interface_addr()
4555 if sender_mac is None:
4556 sender_mac = dev.p2p_interface_addr()
4557 cmd = "DATA_TEST_FRAME "
4558
4559 pkt = build_arp(dst_ll=dst_ll, src_ll=src_ll, opcode=opcode,
4560 sender_mac=sender_mac, sender_ip=sender_ip,
4561 target_mac=target_mac, target_ip=target_ip)
4562 if "OK" not in dev.request(cmd + binascii.hexlify(pkt)):
4563 raise Exception("DATA_TEST_FRAME failed")
4564
4565 def get_permanent_neighbors(ifname):
4566 cmd = subprocess.Popen(['ip', 'nei'], stdout=subprocess.PIPE)
4567 res = cmd.stdout.read()
4568 cmd.stdout.close()
4569 return [ line for line in res.splitlines() if "PERMANENT" in line and ifname in line ]
4570
4571 def get_bridge_macs(ifname):
4572 cmd = subprocess.Popen(['brctl', 'showmacs', ifname],
4573 stdout=subprocess.PIPE)
4574 res = cmd.stdout.read()
4575 cmd.stdout.close()
4576 return res
4577
4578 def tshark_get_arp(cap, filter):
4579 res = run_tshark(cap, filter,
4580 [ "eth.dst", "eth.src",
4581 "arp.src.hw_mac", "arp.src.proto_ipv4",
4582 "arp.dst.hw_mac", "arp.dst.proto_ipv4" ],
4583 wait=False)
4584 frames = []
4585 for l in res.splitlines():
4586 frames.append(l.split('\t'))
4587 return frames
4588
4589 def tshark_get_ns(cap):
4590 res = run_tshark(cap, "icmpv6.type == 135",
4591 [ "eth.dst", "eth.src",
4592 "ipv6.src", "ipv6.dst",
4593 "icmpv6.nd.ns.target_address",
4594 "icmpv6.opt.linkaddr" ],
4595 wait=False)
4596 frames = []
4597 for l in res.splitlines():
4598 frames.append(l.split('\t'))
4599 return frames
4600
4601 def tshark_get_na(cap):
4602 res = run_tshark(cap, "icmpv6.type == 136",
4603 [ "eth.dst", "eth.src",
4604 "ipv6.src", "ipv6.dst",
4605 "icmpv6.nd.na.target_address",
4606 "icmpv6.opt.linkaddr" ],
4607 wait=False)
4608 frames = []
4609 for l in res.splitlines():
4610 frames.append(l.split('\t'))
4611 return frames
4612
4613 def _test_proxyarp_open(dev, apdev, params, ebtables=False):
4614 prefix = "proxyarp_open"
4615 if ebtables:
4616 prefix += "_ebtables"
4617 cap_br = os.path.join(params['logdir'], prefix + ".ap-br0.pcap")
4618 cap_dev0 = os.path.join(params['logdir'],
4619 prefix + ".%s.pcap" % dev[0].ifname)
4620 cap_dev1 = os.path.join(params['logdir'],
4621 prefix + ".%s.pcap" % dev[1].ifname)
4622 cap_dev2 = os.path.join(params['logdir'],
4623 prefix + ".%s.pcap" % dev[2].ifname)
4624
4625 bssid = apdev[0]['bssid']
4626 params = { 'ssid': 'open' }
4627 params['proxy_arp'] = '1'
4628 hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
4629 hapd.set("ap_isolate", "1")
4630 hapd.set('bridge', 'ap-br0')
4631 hapd.dump_monitor()
4632 try:
4633 hapd.enable()
4634 except:
4635 # For now, do not report failures due to missing kernel support
4636 raise HwsimSkip("Could not start hostapd - assume proxyarp not supported in kernel version")
4637 ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=10)
4638 if ev is None:
4639 raise Exception("AP startup timed out")
4640 if "AP-ENABLED" not in ev:
4641 raise Exception("AP startup failed")
4642
4643 params2 = { 'ssid': 'another' }
4644 hapd2 = hostapd.add_ap(apdev[1], params2, no_enable=True)
4645 hapd2.set('bridge', 'ap-br0')
4646 hapd2.enable()
4647
4648 subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
4649 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
4650
4651 if ebtables:
4652 for chain in [ 'FORWARD', 'OUTPUT' ]:
4653 try:
4654 subprocess.call(['ebtables', '-A', chain, '-p', 'ARP',
4655 '-d', 'Broadcast', '-o', apdev[0]['ifname'],
4656 '-j', 'DROP'])
4657 except:
4658 raise HwsimSkip("No ebtables available")
4659
4660 time.sleep(0.5)
4661 cmd = {}
4662 cmd[0] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', 'ap-br0',
4663 '-w', cap_br, '-s', '2000'],
4664 stderr=open('/dev/null', 'w'))
4665 cmd[1] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', dev[0].ifname,
4666 '-w', cap_dev0, '-s', '2000'],
4667 stderr=open('/dev/null', 'w'))
4668 cmd[2] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', dev[1].ifname,
4669 '-w', cap_dev1, '-s', '2000'],
4670 stderr=open('/dev/null', 'w'))
4671 cmd[3] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', dev[2].ifname,
4672 '-w', cap_dev2, '-s', '2000'],
4673 stderr=open('/dev/null', 'w'))
4674
4675 dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
4676 dev[1].connect("open", key_mgmt="NONE", scan_freq="2412")
4677 dev[2].connect("another", key_mgmt="NONE", scan_freq="2412")
4678 time.sleep(0.1)
4679
4680 brcmd = subprocess.Popen(['brctl', 'show'], stdout=subprocess.PIPE)
4681 res = brcmd.stdout.read()
4682 brcmd.stdout.close()
4683 logger.info("Bridge setup: " + res)
4684
4685 brcmd = subprocess.Popen(['brctl', 'showstp', 'ap-br0'],
4686 stdout=subprocess.PIPE)
4687 res = brcmd.stdout.read()
4688 brcmd.stdout.close()
4689 logger.info("Bridge showstp: " + res)
4690
4691 addr0 = dev[0].p2p_interface_addr()
4692 addr1 = dev[1].p2p_interface_addr()
4693 addr2 = dev[2].p2p_interface_addr()
4694
4695 pkt = build_dhcp_ack(dst_ll="ff:ff:ff:ff:ff:ff", src_ll=bssid,
4696 ip_src="192.168.1.1", ip_dst="255.255.255.255",
4697 yiaddr="192.168.1.124", chaddr=addr0)
4698 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
4699 raise Exception("DATA_TEST_FRAME failed")
4700 # Change address and verify unicast
4701 pkt = build_dhcp_ack(dst_ll=addr0, src_ll=bssid,
4702 ip_src="192.168.1.1", ip_dst="255.255.255.255",
4703 yiaddr="192.168.1.123", chaddr=addr0,
4704 udp_checksum=False)
4705 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
4706 raise Exception("DATA_TEST_FRAME failed")
4707
4708 # Not-associated client MAC address
4709 pkt = build_dhcp_ack(dst_ll="ff:ff:ff:ff:ff:ff", src_ll=bssid,
4710 ip_src="192.168.1.1", ip_dst="255.255.255.255",
4711 yiaddr="192.168.1.125", chaddr="22:33:44:55:66:77")
4712 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
4713 raise Exception("DATA_TEST_FRAME failed")
4714
4715 # No IP address
4716 pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
4717 ip_src="192.168.1.1", ip_dst="255.255.255.255",
4718 yiaddr="0.0.0.0", chaddr=addr1)
4719 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
4720 raise Exception("DATA_TEST_FRAME failed")
4721
4722 # Zero subnet mask
4723 pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
4724 ip_src="192.168.1.1", ip_dst="255.255.255.255",
4725 yiaddr="192.168.1.126", chaddr=addr1,
4726 subnet_mask="0.0.0.0")
4727 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
4728 raise Exception("DATA_TEST_FRAME failed")
4729
4730 # Truncated option
4731 pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
4732 ip_src="192.168.1.1", ip_dst="255.255.255.255",
4733 yiaddr="192.168.1.127", chaddr=addr1,
4734 truncated_opt=True)
4735 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
4736 raise Exception("DATA_TEST_FRAME failed")
4737
4738 # Wrong magic
4739 pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
4740 ip_src="192.168.1.1", ip_dst="255.255.255.255",
4741 yiaddr="192.168.1.128", chaddr=addr1,
4742 wrong_magic=True)
4743 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
4744 raise Exception("DATA_TEST_FRAME failed")
4745
4746 # Wrong IPv4 total length
4747 pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
4748 ip_src="192.168.1.1", ip_dst="255.255.255.255",
4749 yiaddr="192.168.1.129", chaddr=addr1,
4750 force_tot_len=1000)
4751 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
4752 raise Exception("DATA_TEST_FRAME failed")
4753
4754 # BOOTP
4755 pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
4756 ip_src="192.168.1.1", ip_dst="255.255.255.255",
4757 yiaddr="192.168.1.129", chaddr=addr1,
4758 no_dhcp=True)
4759 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
4760 raise Exception("DATA_TEST_FRAME failed")
4761
4762 macs = get_bridge_macs("ap-br0")
4763 logger.info("After connect (showmacs): " + str(macs))
4764
4765 matches = get_permanent_neighbors("ap-br0")
4766 logger.info("After connect: " + str(matches))
4767 if len(matches) != 1:
4768 raise Exception("Unexpected number of neighbor entries after connect")
4769 if '192.168.1.123 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
4770 raise Exception("dev0 IPv4 addr missing")
4771
4772 targets = [ "192.168.1.123", "192.168.1.124", "192.168.1.125",
4773 "192.168.1.126" ]
4774 for target in targets:
4775 send_arp(dev[1], sender_ip="192.168.1.100", target_ip=target)
4776
4777 for target in targets:
4778 send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.101",
4779 target_ip=target)
4780
4781 for target in targets:
4782 send_arp(dev[2], sender_ip="192.168.1.103", target_ip=target)
4783
4784 # ARP Probe from wireless STA
4785 send_arp(dev[1], target_ip="192.168.1.127")
4786 # ARP Announcement from wireless STA
4787 send_arp(dev[1], sender_ip="192.168.1.127", target_ip="192.168.1.127")
4788 send_arp(dev[1], sender_ip="192.168.1.127", target_ip="192.168.1.127",
4789 opcode=2)
4790
4791 macs = get_bridge_macs("ap-br0")
4792 logger.info("After ARP Probe + Announcement (showmacs): " + str(macs))
4793
4794 matches = get_permanent_neighbors("ap-br0")
4795 logger.info("After ARP Probe + Announcement: " + str(matches))
4796
4797 # ARP Request for the newly introduced IP address from wireless STA
4798 send_arp(dev[0], sender_ip="192.168.1.123", target_ip="192.168.1.127")
4799
4800 # ARP Request for the newly introduced IP address from bridge
4801 send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.102",
4802 target_ip="192.168.1.127")
4803 send_arp(dev[2], sender_ip="192.168.1.103", target_ip="192.168.1.127")
4804
4805 # ARP Probe from bridge
4806 send_arp(hapd, hapd_bssid=bssid, target_ip="192.168.1.130")
4807 send_arp(dev[2], target_ip="192.168.1.131")
4808 # ARP Announcement from bridge (not to be learned by AP for proxyarp)
4809 send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.130",
4810 target_ip="192.168.1.130")
4811 send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.130",
4812 target_ip="192.168.1.130", opcode=2)
4813 send_arp(dev[2], sender_ip="192.168.1.131", target_ip="192.168.1.131")
4814 send_arp(dev[2], sender_ip="192.168.1.131", target_ip="192.168.1.131",
4815 opcode=2)
4816
4817 macs = get_bridge_macs("ap-br0")
4818 logger.info("After ARP Probe + Announcement (showmacs): " + str(macs))
4819
4820 matches = get_permanent_neighbors("ap-br0")
4821 logger.info("After ARP Probe + Announcement: " + str(matches))
4822
4823 # ARP Request for the newly introduced IP address from wireless STA
4824 send_arp(dev[0], sender_ip="192.168.1.123", target_ip="192.168.1.130")
4825 # ARP Response from bridge (AP does not proxy for non-wireless devices)
4826 send_arp(hapd, hapd_bssid=bssid, dst_ll=addr0, sender_ip="192.168.1.130",
4827 target_ip="192.168.1.123", opcode=2)
4828
4829 # ARP Request for the newly introduced IP address from wireless STA
4830 send_arp(dev[0], sender_ip="192.168.1.123", target_ip="192.168.1.131")
4831 # ARP Response from bridge (AP does not proxy for non-wireless devices)
4832 send_arp(dev[2], dst_ll=addr0, sender_ip="192.168.1.131",
4833 target_ip="192.168.1.123", opcode=2)
4834
4835 # ARP Request for the newly introduced IP address from bridge
4836 send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.102",
4837 target_ip="192.168.1.130")
4838 send_arp(dev[2], sender_ip="192.168.1.104", target_ip="192.168.1.131")
4839
4840 # ARP Probe from wireless STA (duplicate address; learned through DHCP)
4841 send_arp(dev[1], target_ip="192.168.1.123")
4842 # ARP Probe from wireless STA (duplicate address; learned through ARP)
4843 send_arp(dev[0], target_ip="192.168.1.127")
4844
4845 # Gratuitous ARP Reply for another STA's IP address
4846 send_arp(dev[0], opcode=2, sender_mac=addr0, sender_ip="192.168.1.127",
4847 target_mac=addr1, target_ip="192.168.1.127")
4848 send_arp(dev[1], opcode=2, sender_mac=addr1, sender_ip="192.168.1.123",
4849 target_mac=addr0, target_ip="192.168.1.123")
4850 # ARP Request to verify previous mapping
4851 send_arp(dev[1], sender_ip="192.168.1.127", target_ip="192.168.1.123")
4852 send_arp(dev[0], sender_ip="192.168.1.123", target_ip="192.168.1.127")
4853
4854 try:
4855 hwsim_utils.test_connectivity_iface(dev[0], hapd, "ap-br0")
4856 except Exception as e:
4857 logger.info("test_connectibity_iface failed: " + str(e))
4858 raise HwsimSkip("Assume kernel did not have the required patches for proxyarp")
4859 hwsim_utils.test_connectivity_iface(dev[1], hapd, "ap-br0")
4860 hwsim_utils.test_connectivity(dev[0], dev[1])
4861
4862 dev[0].request("DISCONNECT")
4863 dev[1].request("DISCONNECT")
4864 time.sleep(0.5)
4865 for i in range(len(cmd)):
4866 cmd[i].terminate()
4867 macs = get_bridge_macs("ap-br0")
4868 logger.info("After disconnect (showmacs): " + str(macs))
4869 matches = get_permanent_neighbors("ap-br0")
4870 logger.info("After disconnect: " + str(matches))
4871 if len(matches) > 0:
4872 raise Exception("Unexpected neighbor entries after disconnect")
4873 if ebtables:
4874 cmd = subprocess.Popen(['ebtables', '-L', '--Lc'],
4875 stdout=subprocess.PIPE)
4876 res = cmd.stdout.read()
4877 cmd.stdout.close()
4878 logger.info("ebtables results:\n" + res)
4879
4880 # Verify that expected ARP messages were seen and no unexpected
4881 # ARP messages were seen.
4882
4883 arp_req = tshark_get_arp(cap_dev0, "arp.opcode == 1")
4884 arp_reply = tshark_get_arp(cap_dev0, "arp.opcode == 2")
4885 logger.info("dev0 seen ARP requests:\n" + str(arp_req))
4886 logger.info("dev0 seen ARP replies:\n" + str(arp_reply))
4887
4888 if [ 'ff:ff:ff:ff:ff:ff', addr1,
4889 addr1, '192.168.1.100',
4890 '00:00:00:00:00:00', '192.168.1.123' ] in arp_req:
4891 raise Exception("dev0 saw ARP request from dev1")
4892 if [ 'ff:ff:ff:ff:ff:ff', addr2,
4893 addr2, '192.168.1.103',
4894 '00:00:00:00:00:00', '192.168.1.123' ] in arp_req:
4895 raise Exception("dev0 saw ARP request from dev2")
4896 # TODO: Uncomment once fixed in kernel
4897 #if [ 'ff:ff:ff:ff:ff:ff', bssid,
4898 # bssid, '192.168.1.101',
4899 # '00:00:00:00:00:00', '192.168.1.123' ] in arp_req:
4900 # raise Exception("dev0 saw ARP request from br")
4901
4902 if ebtables:
4903 for req in arp_req:
4904 if req[1] != addr0:
4905 raise Exception("Unexpected foreign ARP request on dev0")
4906
4907 arp_req = tshark_get_arp(cap_dev1, "arp.opcode == 1")
4908 arp_reply = tshark_get_arp(cap_dev1, "arp.opcode == 2")
4909 logger.info("dev1 seen ARP requests:\n" + str(arp_req))
4910 logger.info("dev1 seen ARP replies:\n" + str(arp_reply))
4911
4912 if [ 'ff:ff:ff:ff:ff:ff', addr2,
4913 addr2, '192.168.1.103',
4914 '00:00:00:00:00:00', '192.168.1.123' ] in arp_req:
4915 raise Exception("dev1 saw ARP request from dev2")
4916 if [addr1, addr0, addr0, '192.168.1.123', addr1, '192.168.1.100'] not in arp_reply:
4917 raise Exception("dev1 did not get ARP response for 192.168.1.123")
4918
4919 if ebtables:
4920 for req in arp_req:
4921 if req[1] != addr1:
4922 raise Exception("Unexpected foreign ARP request on dev1")
4923
4924 arp_req = tshark_get_arp(cap_dev2, "arp.opcode == 1")
4925 arp_reply = tshark_get_arp(cap_dev2, "arp.opcode == 2")
4926 logger.info("dev2 seen ARP requests:\n" + str(arp_req))
4927 logger.info("dev2 seen ARP replies:\n" + str(arp_reply))
4928
4929 if [ addr2, addr0,
4930 addr0, '192.168.1.123',
4931 addr2, '192.168.1.103' ] not in arp_reply:
4932 raise Exception("dev2 did not get ARP response for 192.168.1.123")
4933
4934 arp_req = tshark_get_arp(cap_br, "arp.opcode == 1")
4935 arp_reply = tshark_get_arp(cap_br, "arp.opcode == 2")
4936 logger.info("br seen ARP requests:\n" + str(arp_req))
4937 logger.info("br seen ARP replies:\n" + str(arp_reply))
4938
4939 # TODO: Uncomment once fixed in kernel
4940 #if [ bssid, addr0,
4941 # addr0, '192.168.1.123',
4942 # bssid, '192.168.1.101' ] not in arp_reply:
4943 # raise Exception("br did not get ARP response for 192.168.1.123")
4944
4945 def _test_proxyarp_open_ipv6(dev, apdev, params, ebtables=False):
4946 prefix = "proxyarp_open"
4947 if ebtables:
4948 prefix += "_ebtables"
4949 cap_br = os.path.join(params['logdir'], prefix + ".ap-br0.pcap")
4950 cap_dev0 = os.path.join(params['logdir'],
4951 prefix + ".%s.pcap" % dev[0].ifname)
4952 cap_dev1 = os.path.join(params['logdir'],
4953 prefix + ".%s.pcap" % dev[1].ifname)
4954 cap_dev2 = os.path.join(params['logdir'],
4955 prefix + ".%s.pcap" % dev[2].ifname)
4956
4957 bssid = apdev[0]['bssid']
4958 params = { 'ssid': 'open' }
4959 params['proxy_arp'] = '1'
4960 hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
4961 hapd.set("ap_isolate", "1")
4962 hapd.set('bridge', 'ap-br0')
4963 hapd.dump_monitor()
4964 try:
4965 hapd.enable()
4966 except:
4967 # For now, do not report failures due to missing kernel support
4968 raise HwsimSkip("Could not start hostapd - assume proxyarp not supported in kernel version")
4969 ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=10)
4970 if ev is None:
4971 raise Exception("AP startup timed out")
4972 if "AP-ENABLED" not in ev:
4973 raise Exception("AP startup failed")
4974
4975 params2 = { 'ssid': 'another' }
4976 hapd2 = hostapd.add_ap(apdev[1], params2, no_enable=True)
4977 hapd2.set('bridge', 'ap-br0')
4978 hapd2.enable()
4979
4980 subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
4981 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
4982
4983 if ebtables:
4984 for chain in [ 'FORWARD', 'OUTPUT' ]:
4985 try:
4986 subprocess.call(['ebtables', '-A', chain, '-d', 'Multicast',
4987 '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp',
4988 '--ip6-icmp-type', 'neighbor-solicitation',
4989 '-o', apdev[0]['ifname'], '-j', 'DROP'])
4990 subprocess.call(['ebtables', '-A', chain, '-d', 'Multicast',
4991 '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp',
4992 '--ip6-icmp-type', 'neighbor-advertisement',
4993 '-o', apdev[0]['ifname'], '-j', 'DROP'])
4994 subprocess.call(['ebtables', '-A', chain,
4995 '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp',
4996 '--ip6-icmp-type', 'router-solicitation',
4997 '-o', apdev[0]['ifname'], '-j', 'DROP'])
4998 # Multicast Listener Report Message
4999 subprocess.call(['ebtables', '-A', chain, '-d', 'Multicast',
5000 '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp',
5001 '--ip6-icmp-type', '143',
5002 '-o', apdev[0]['ifname'], '-j', 'DROP'])
5003 except:
5004 raise HwsimSkip("No ebtables available")
5005
5006 time.sleep(0.5)
5007 cmd = {}
5008 cmd[0] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', 'ap-br0',
5009 '-w', cap_br, '-s', '2000'],
5010 stderr=open('/dev/null', 'w'))
5011 cmd[1] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', dev[0].ifname,
5012 '-w', cap_dev0, '-s', '2000'],
5013 stderr=open('/dev/null', 'w'))
5014 cmd[2] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', dev[1].ifname,
5015 '-w', cap_dev1, '-s', '2000'],
5016 stderr=open('/dev/null', 'w'))
5017 cmd[3] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', dev[2].ifname,
5018 '-w', cap_dev2, '-s', '2000'],
5019 stderr=open('/dev/null', 'w'))
5020
5021 dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
5022 dev[1].connect("open", key_mgmt="NONE", scan_freq="2412")
5023 dev[2].connect("another", key_mgmt="NONE", scan_freq="2412")
5024 time.sleep(0.1)
5025
5026 brcmd = subprocess.Popen(['brctl', 'show'], stdout=subprocess.PIPE)
5027 res = brcmd.stdout.read()
5028 brcmd.stdout.close()
5029 logger.info("Bridge setup: " + res)
5030
5031 brcmd = subprocess.Popen(['brctl', 'showstp', 'ap-br0'],
5032 stdout=subprocess.PIPE)
5033 res = brcmd.stdout.read()
5034 brcmd.stdout.close()
5035 logger.info("Bridge showstp: " + res)
5036
5037 addr0 = dev[0].p2p_interface_addr()
5038 addr1 = dev[1].p2p_interface_addr()
5039 addr2 = dev[2].p2p_interface_addr()
5040
5041 src_ll_opt0 = "\x01\x01" + binascii.unhexlify(addr0.replace(':',''))
5042 src_ll_opt1 = "\x01\x01" + binascii.unhexlify(addr1.replace(':',''))
5043
5044 # DAD NS
5045 send_ns(dev[0], ip_src="::", target="aaaa:bbbb:cccc::2")
5046
5047 send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2")
5048 # test frame without source link-layer address option
5049 send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2",
5050 opt='')
5051 # test frame with bogus option
5052 send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2",
5053 opt="\x70\x01\x01\x02\x03\x04\x05\x05")
5054 # test frame with truncated source link-layer address option
5055 send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2",
5056 opt="\x01\x01\x01\x02\x03\x04")
5057 # test frame with foreign source link-layer address option
5058 send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2",
5059 opt="\x01\x01\x01\x02\x03\x04\x05\x06")
5060
5061 send_ns(dev[1], ip_src="aaaa:bbbb:dddd::2", target="aaaa:bbbb:dddd::2")
5062
5063 send_ns(dev[1], ip_src="aaaa:bbbb:eeee::2", target="aaaa:bbbb:eeee::2")
5064 # another copy for additional code coverage
5065 send_ns(dev[1], ip_src="aaaa:bbbb:eeee::2", target="aaaa:bbbb:eeee::2")
5066
5067 macs = get_bridge_macs("ap-br0")
5068 logger.info("After connect (showmacs): " + str(macs))
5069
5070 matches = get_permanent_neighbors("ap-br0")
5071 logger.info("After connect: " + str(matches))
5072 if len(matches) != 3:
5073 raise Exception("Unexpected number of neighbor entries after connect")
5074 if 'aaaa:bbbb:cccc::2 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
5075 raise Exception("dev0 addr missing")
5076 if 'aaaa:bbbb:dddd::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches:
5077 raise Exception("dev1 addr(1) missing")
5078 if 'aaaa:bbbb:eeee::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches:
5079 raise Exception("dev1 addr(2) missing")
5080
5081 send_ns(dev[0], target="aaaa:bbbb:dddd::2", ip_src="aaaa:bbbb:cccc::2")
5082 time.sleep(0.1)
5083 send_ns(dev[1], target="aaaa:bbbb:cccc::2", ip_src="aaaa:bbbb:dddd::2")
5084 time.sleep(0.1)
5085 send_ns(hapd, hapd_bssid=bssid, target="aaaa:bbbb:dddd::2",
5086 ip_src="aaaa:bbbb:ffff::2")
5087 time.sleep(0.1)
5088 send_ns(dev[2], target="aaaa:bbbb:cccc::2", ip_src="aaaa:bbbb:ff00::2")
5089 time.sleep(0.1)
5090 send_ns(dev[2], target="aaaa:bbbb:dddd::2", ip_src="aaaa:bbbb:ff00::2")
5091 time.sleep(0.1)
5092 send_ns(dev[2], target="aaaa:bbbb:eeee::2", ip_src="aaaa:bbbb:ff00::2")
5093 time.sleep(0.1)
5094
5095 # Try to probe for an already assigned address
5096 send_ns(dev[1], target="aaaa:bbbb:cccc::2", ip_src="::")
5097 time.sleep(0.1)
5098 send_ns(hapd, hapd_bssid=bssid, target="aaaa:bbbb:cccc::2", ip_src="::")
5099 time.sleep(0.1)
5100 send_ns(dev[2], target="aaaa:bbbb:cccc::2", ip_src="::")
5101 time.sleep(0.1)
5102
5103 # Unsolicited NA
5104 send_na(dev[1], target="aaaa:bbbb:cccc:aeae::3",
5105 ip_src="aaaa:bbbb:cccc:aeae::3", ip_dst="ff02::1")
5106 send_na(hapd, hapd_bssid=bssid, target="aaaa:bbbb:cccc:aeae::4",
5107 ip_src="aaaa:bbbb:cccc:aeae::4", ip_dst="ff02::1")
5108 send_na(dev[2], target="aaaa:bbbb:cccc:aeae::5",
5109 ip_src="aaaa:bbbb:cccc:aeae::5", ip_dst="ff02::1")
5110
5111 try:
5112 hwsim_utils.test_connectivity_iface(dev[0], hapd, "ap-br0")
5113 except Exception as e:
5114 logger.info("test_connectibity_iface failed: " + str(e))
5115 raise HwsimSkip("Assume kernel did not have the required patches for proxyarp")
5116 hwsim_utils.test_connectivity_iface(dev[1], hapd, "ap-br0")
5117 hwsim_utils.test_connectivity(dev[0], dev[1])
5118
5119 dev[0].request("DISCONNECT")
5120 dev[1].request("DISCONNECT")
5121 time.sleep(0.5)
5122 for i in range(len(cmd)):
5123 cmd[i].terminate()
5124 macs = get_bridge_macs("ap-br0")
5125 logger.info("After disconnect (showmacs): " + str(macs))
5126 matches = get_permanent_neighbors("ap-br0")
5127 logger.info("After disconnect: " + str(matches))
5128 if len(matches) > 0:
5129 raise Exception("Unexpected neighbor entries after disconnect")
5130 if ebtables:
5131 cmd = subprocess.Popen(['ebtables', '-L', '--Lc'],
5132 stdout=subprocess.PIPE)
5133 res = cmd.stdout.read()
5134 cmd.stdout.close()
5135 logger.info("ebtables results:\n" + res)
5136
5137 ns = tshark_get_ns(cap_dev0)
5138 logger.info("dev0 seen NS: " + str(ns))
5139 na = tshark_get_na(cap_dev0)
5140 logger.info("dev0 seen NA: " + str(na))
5141
5142 if [ addr0, addr1, 'aaaa:bbbb:dddd::2', 'aaaa:bbbb:cccc::2',
5143 'aaaa:bbbb:dddd::2', addr1 ] not in na:
5144 # For now, skip the test instead of reporting the error since the IPv6
5145 # proxyarp support is not yet in the upstream kernel tree.
5146 #raise Exception("dev0 did not get NA for aaaa:bbbb:dddd::2")
5147 raise HwsimSkip("Assume kernel did not have the required patches for proxyarp (IPv6)")
5148
5149 if ebtables:
5150 for req in ns:
5151 if req[1] != addr0:
5152 raise Exception("Unexpected foreign NS on dev0: " + str(req))
5153
5154 ns = tshark_get_ns(cap_dev1)
5155 logger.info("dev1 seen NS: " + str(ns))
5156 na = tshark_get_na(cap_dev1)
5157 logger.info("dev1 seen NA: " + str(na))
5158
5159 if [ addr1, addr0, 'aaaa:bbbb:cccc::2', 'aaaa:bbbb:dddd::2',
5160 'aaaa:bbbb:cccc::2', addr0 ] not in na:
5161 raise Exception("dev1 did not get NA for aaaa:bbbb:cccc::2")
5162
5163 if ebtables:
5164 for req in ns:
5165 if req[1] != addr1:
5166 raise Exception("Unexpected foreign NS on dev1: " + str(req))
5167
5168 ns = tshark_get_ns(cap_dev2)
5169 logger.info("dev2 seen NS: " + str(ns))
5170 na = tshark_get_na(cap_dev2)
5171 logger.info("dev2 seen NA: " + str(na))
5172
5173 # FIX: enable once kernel implementation for proxyarp IPv6 is fixed
5174 #if [ addr2, addr0, 'aaaa:bbbb:cccc::2', 'aaaa:bbbb:ff00::2',
5175 # 'aaaa:bbbb:cccc::2', addr0 ] not in na:
5176 # raise Exception("dev2 did not get NA for aaaa:bbbb:cccc::2")
5177 #if [ addr2, addr1, 'aaaa:bbbb:dddd::2', 'aaaa:bbbb:ff00::2',
5178 # 'aaaa:bbbb:dddd::2', addr1 ] not in na:
5179 # raise Exception("dev2 did not get NA for aaaa:bbbb:dddd::2")
5180 #if [ addr2, addr1, 'aaaa:bbbb:eeee::2', 'aaaa:bbbb:ff00::2',
5181 # 'aaaa:bbbb:eeee::2', addr1 ] not in na:
5182 # raise Exception("dev2 did not get NA for aaaa:bbbb:eeee::2")
5183
5184 def test_proxyarp_open(dev, apdev, params):
5185 """ProxyARP with open network"""
5186 try:
5187 _test_proxyarp_open(dev, apdev, params)
5188 finally:
5189 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
5190 stderr=open('/dev/null', 'w'))
5191 subprocess.call(['brctl', 'delbr', 'ap-br0'],
5192 stderr=open('/dev/null', 'w'))
5193
5194 def test_proxyarp_open_ipv6(dev, apdev, params):
5195 """ProxyARP with open network (IPv6)"""
5196 try:
5197 _test_proxyarp_open_ipv6(dev, apdev, params)
5198 finally:
5199 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
5200 stderr=open('/dev/null', 'w'))
5201 subprocess.call(['brctl', 'delbr', 'ap-br0'],
5202 stderr=open('/dev/null', 'w'))
5203
5204 def test_proxyarp_open_ebtables(dev, apdev, params):
5205 """ProxyARP with open network"""
5206 try:
5207 _test_proxyarp_open(dev, apdev, params, ebtables=True)
5208 finally:
5209 try:
5210 subprocess.call(['ebtables', '-F', 'FORWARD'])
5211 subprocess.call(['ebtables', '-F', 'OUTPUT'])
5212 except:
5213 pass
5214 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
5215 stderr=open('/dev/null', 'w'))
5216 subprocess.call(['brctl', 'delbr', 'ap-br0'],
5217 stderr=open('/dev/null', 'w'))
5218
5219 def test_proxyarp_open_ebtables_ipv6(dev, apdev, params):
5220 """ProxyARP with open network (IPv6)"""
5221 try:
5222 _test_proxyarp_open_ipv6(dev, apdev, params, ebtables=True)
5223 finally:
5224 try:
5225 subprocess.call(['ebtables', '-F', 'FORWARD'])
5226 subprocess.call(['ebtables', '-F', 'OUTPUT'])
5227 except:
5228 pass
5229 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
5230 stderr=open('/dev/null', 'w'))
5231 subprocess.call(['brctl', 'delbr', 'ap-br0'],
5232 stderr=open('/dev/null', 'w'))
5233
5234 def test_proxyarp_errors(dev, apdev, params):
5235 """ProxyARP error cases"""
5236 try:
5237 run_proxyarp_errors(dev, apdev, params)
5238 finally:
5239 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
5240 stderr=open('/dev/null', 'w'))
5241 subprocess.call(['brctl', 'delbr', 'ap-br0'],
5242 stderr=open('/dev/null', 'w'))
5243
5244 def run_proxyarp_errors(dev, apdev, params):
5245 params = { 'ssid': 'open',
5246 'proxy_arp': '1',
5247 'ap_isolate': '1',
5248 'bridge': 'ap-br0',
5249 'disable_dgaf': '1' }
5250 hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
5251 try:
5252 hapd.enable()
5253 except:
5254 # For now, do not report failures due to missing kernel support
5255 raise HwsimSkip("Could not start hostapd - assume proxyarp not supported in kernel version")
5256 ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=10)
5257 if ev is None:
5258 raise Exception("AP startup timed out")
5259 if "AP-ENABLED" not in ev:
5260 raise Exception("AP startup failed")
5261
5262 hapd.disable()
5263 with alloc_fail(hapd, 1, "l2_packet_init;x_snoop_get_l2_packet;dhcp_snoop_init"):
5264 if "FAIL" not in hapd.request("ENABLE"):
5265 raise Exception("ENABLE accepted unexpectedly")
5266 with alloc_fail(hapd, 1, "l2_packet_init;x_snoop_get_l2_packet;ndisc_snoop_init"):
5267 if "FAIL" not in hapd.request("ENABLE"):
5268 raise Exception("ENABLE accepted unexpectedly")
5269 with fail_test(hapd, 1, "l2_packet_set_packet_filter;x_snoop_get_l2_packet;ndisc_snoop_init"):
5270 if "FAIL" not in hapd.request("ENABLE"):
5271 raise Exception("ENABLE accepted unexpectedly")
5272 with fail_test(hapd, 1, "l2_packet_set_packet_filter;x_snoop_get_l2_packet;dhcp_snoop_init"):
5273 if "FAIL" not in hapd.request("ENABLE"):
5274 raise Exception("ENABLE accepted unexpectedly")
5275 hapd.enable()
5276
5277 subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
5278 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
5279
5280 dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
5281 addr0 = dev[0].own_addr()
5282
5283 pkt = build_ra(src_ll=apdev[0]['bssid'], ip_src="aaaa:bbbb:cccc::33",
5284 ip_dst="ff01::1")
5285 with fail_test(hapd, 1, "x_snoop_mcast_to_ucast_convert_send"):
5286 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
5287 raise Exception("DATA_TEST_FRAME failed")
5288 wait_fail_trigger(dev[0], "GET_FAIL")
5289
5290 with alloc_fail(hapd, 1, "sta_ip6addr_add"):
5291 src_ll_opt0 = "\x01\x01" + binascii.unhexlify(addr0.replace(':',''))
5292 pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
5293 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2",
5294 opt=src_ll_opt0)
5295 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
5296 raise Exception("DATA_TEST_FRAME failed")
5297 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5298
5299 def test_ap_hs20_connect_deinit(dev, apdev):
5300 """Hotspot 2.0 connection interrupted with deinit"""
5301 check_eap_capa(dev[0], "MSCHAPV2")
5302 bssid = apdev[0]['bssid']
5303 params = hs20_ap_params()
5304 params['hessid'] = bssid
5305 hapd = hostapd.add_ap(apdev[0], params)
5306
5307 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
5308 wpas.interface_add("wlan5", drv_params="")
5309 wpas.hs20_enable()
5310 wpas.flush_scan_cache()
5311 wpas.add_cred_values({ 'realm': "example.com",
5312 'username': "hs20-test",
5313 'password': "password",
5314 'ca_cert': "auth_serv/ca.pem",
5315 'domain': "example.com" })
5316
5317 wpas.scan_for_bss(bssid, freq=2412)
5318 hapd.disable()
5319
5320 wpas.request("INTERWORKING_SELECT freq=2412")
5321
5322 id = wpas.request("RADIO_WORK add block-work")
5323 ev = wpas.wait_event(["GAS-QUERY-START", "EXT-RADIO-WORK-START"], timeout=5)
5324 if ev is None:
5325 raise Exception("Timeout while waiting radio work to start")
5326 ev = wpas.wait_event(["GAS-QUERY-START", "EXT-RADIO-WORK-START"], timeout=5)
5327 if ev is None:
5328 raise Exception("Timeout while waiting radio work to start (2)")
5329
5330 # Remove the interface while the gas-query radio work is still pending and
5331 # GAS query has not yet been started.
5332 wpas.interface_remove("wlan5")
5333
5334 def test_ap_hs20_anqp_format_errors(dev, apdev):
5335 """Interworking network selection and ANQP format errors"""
5336 bssid = apdev[0]['bssid']
5337 params = hs20_ap_params()
5338 params['hessid'] = bssid
5339 hapd = hostapd.add_ap(apdev[0], params)
5340
5341 dev[0].hs20_enable()
5342 values = { 'realm': "example.com",
5343 'ca_cert': "auth_serv/ca.pem",
5344 'username': "hs20-test",
5345 'password': "password",
5346 'domain': "example.com" }
5347 id = dev[0].add_cred_values(values)
5348
5349 dev[0].scan_for_bss(bssid, freq="2412")
5350
5351 tests = [ "00", "ffff", "010011223344", "020008000005112233445500",
5352 "01000400000000", "01000000000000",
5353 "01000300000200", "0100040000ff0000", "01000300000100",
5354 "01000300000001",
5355 "01000600000056112233",
5356 "01000900000002050001000111",
5357 "01000600000001000000", "01000600000001ff0000",
5358 "01000600000001020001",
5359 "010008000000010400010001", "0100080000000104000100ff",
5360 "010011000000010d00050200020100030005000600",
5361 "0000" ]
5362 for t in tests:
5363 hapd.set("anqp_elem", "263:" + t)
5364 dev[0].request("INTERWORKING_SELECT freq=2412")
5365 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=5)
5366 if ev is None:
5367 raise Exception("Network selection timed out")
5368 dev[0].dump_monitor()
5369
5370 dev[0].remove_cred(id)
5371 id = dev[0].add_cred_values({ 'imsi': "555444-333222111", 'eap': "AKA",
5372 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"})
5373
5374 tests = [ "00", "0100", "0001", "00ff", "000200ff", "0003000101",
5375 "00020100" ]
5376 for t in tests:
5377 hapd.set("anqp_elem", "264:" + t)
5378 dev[0].request("INTERWORKING_SELECT freq=2412")
5379 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=5)
5380 if ev is None:
5381 raise Exception("Network selection timed out")
5382 dev[0].dump_monitor()
5383
5384 def test_ap_hs20_cred_with_nai_realm(dev, apdev):
5385 """Hotspot 2.0 network selection and cred_with_nai_realm cred->realm"""
5386 bssid = apdev[0]['bssid']
5387 params = hs20_ap_params()
5388 params['hessid'] = bssid
5389 hostapd.add_ap(apdev[0], params)
5390
5391 dev[0].hs20_enable()
5392
5393 id = dev[0].add_cred_values({ 'realm': "example.com",
5394 'username': "test",
5395 'password': "secret",
5396 'domain': "example.com",
5397 'eap': 'TTLS' })
5398 interworking_select(dev[0], bssid, "home", freq=2412)
5399 dev[0].remove_cred(id)
5400
5401 id = dev[0].add_cred_values({ 'realm': "foo.com",
5402 'username': "test",
5403 'password': "secret",
5404 'domain': "example.com",
5405 'roaming_consortium': "112234",
5406 'eap': 'TTLS' })
5407 interworking_select(dev[0], bssid, "home", freq=2412, no_match=True)
5408 dev[0].remove_cred(id)
5409
5410 def test_ap_hs20_cred_and_no_roaming_consortium(dev, apdev):
5411 """Hotspot 2.0 network selection and no roaming consortium"""
5412 bssid = apdev[0]['bssid']
5413 params = hs20_ap_params()
5414 params['hessid'] = bssid
5415 del params['roaming_consortium']
5416 hostapd.add_ap(apdev[0], params)
5417
5418 dev[0].hs20_enable()
5419
5420 id = dev[0].add_cred_values({ 'realm': "example.com",
5421 'username': "test",
5422 'password': "secret",
5423 'domain': "example.com",
5424 'roaming_consortium': "112234",
5425 'eap': 'TTLS' })
5426 interworking_select(dev[0], bssid, "home", freq=2412, no_match=True)
5427
5428 def test_ap_hs20_interworking_oom(dev, apdev):
5429 """Hotspot 2.0 network selection and OOM"""
5430 bssid = apdev[0]['bssid']
5431 params = hs20_ap_params()
5432 params['hessid'] = bssid
5433 params['nai_realm'] = [ "0,no.match.here;example.com;no.match.here.either,21[2:1][5:7]",
5434 "0,example.com,13[5:6],21[2:4][5:7]",
5435 "0,another.example.com" ]
5436 hostapd.add_ap(apdev[0], params)
5437
5438 dev[0].hs20_enable()
5439
5440 id = dev[0].add_cred_values({ 'realm': "example.com",
5441 'username': "test",
5442 'password': "secret",
5443 'domain': "example.com",
5444 'eap': 'TTLS' })
5445
5446 dev[0].scan_for_bss(bssid, freq="2412")
5447
5448 funcs = [ "wpabuf_alloc;interworking_anqp_send_req",
5449 "anqp_build_req;interworking_anqp_send_req",
5450 "gas_query_req;interworking_anqp_send_req",
5451 "dup_binstr;nai_realm_parse_realm",
5452 "=nai_realm_parse_realm",
5453 "=nai_realm_parse",
5454 "=nai_realm_match" ]
5455 for func in funcs:
5456 with alloc_fail(dev[0], 1, func):
5457 dev[0].request("INTERWORKING_SELECT auto freq=2412")
5458 ev = dev[0].wait_event(["Starting ANQP"], timeout=5)
5459 if ev is None:
5460 raise Exception("ANQP did not start")
5461 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5462
5463 def test_ap_hs20_no_cred_connect(dev, apdev):
5464 """Hotspot 2.0 and connect attempt without credential"""
5465 bssid = apdev[0]['bssid']
5466 params = hs20_ap_params()
5467 params['hessid'] = bssid
5468 hapd = hostapd.add_ap(apdev[0], params)
5469
5470 dev[0].hs20_enable()
5471 dev[0].scan_for_bss(bssid, freq="2412")
5472 if "FAIL" not in dev[0].request("INTERWORKING_CONNECT " + bssid):
5473 raise Exception("Unexpected INTERWORKING_CONNECT success")
5474
5475 def test_ap_hs20_no_rsn_connect(dev, apdev):
5476 """Hotspot 2.0 and connect attempt without RSN"""
5477 bssid = apdev[0]['bssid']
5478 params = hostapd.wpa_params(ssid="test-hs20")
5479 params['wpa_key_mgmt'] = "WPA-EAP"
5480 params['ieee80211w'] = "1"
5481 params['ieee8021x'] = "1"
5482 params['auth_server_addr'] = "127.0.0.1"
5483 params['auth_server_port'] = "1812"
5484 params['auth_server_shared_secret'] = "radius"
5485 params['interworking'] = "1"
5486 params['roaming_consortium'] = [ "112233", "1020304050", "010203040506",
5487 "fedcba" ]
5488 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]",
5489 "0,another.example.com" ]
5490 hapd = hostapd.add_ap(apdev[0], params)
5491
5492 dev[0].hs20_enable()
5493 dev[0].scan_for_bss(bssid, freq="2412")
5494
5495 id = dev[0].add_cred_values({ 'realm': "example.com",
5496 'username': "test",
5497 'password': "secret",
5498 'domain': "example.com",
5499 'roaming_consortium': "112233",
5500 'eap': 'TTLS' })
5501
5502 interworking_select(dev[0], bssid, freq=2412, no_match=True)
5503 if "FAIL" not in dev[0].request("INTERWORKING_CONNECT " + bssid):
5504 raise Exception("Unexpected INTERWORKING_CONNECT success")
5505
5506 def test_ap_hs20_no_match_connect(dev, apdev):
5507 """Hotspot 2.0 and connect attempt without matching cred"""
5508 bssid = apdev[0]['bssid']
5509 params = hs20_ap_params()
5510 hapd = hostapd.add_ap(apdev[0], params)
5511
5512 dev[0].hs20_enable()
5513 dev[0].scan_for_bss(bssid, freq="2412")
5514
5515 id = dev[0].add_cred_values({ 'realm': "example.org",
5516 'username': "test",
5517 'password': "secret",
5518 'domain': "example.org",
5519 'roaming_consortium': "112234",
5520 'eap': 'TTLS' })
5521
5522 interworking_select(dev[0], bssid, freq=2412, no_match=True)
5523 if "FAIL" not in dev[0].request("INTERWORKING_CONNECT " + bssid):
5524 raise Exception("Unexpected INTERWORKING_CONNECT success")
5525
5526 def test_ap_hs20_multiple_home_cred(dev, apdev):
5527 """Hotspot 2.0 and select with multiple matching home credentials"""
5528 bssid = apdev[0]['bssid']
5529 params = hs20_ap_params()
5530 params['hessid'] = bssid
5531 params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]" ]
5532 params['domain_name'] = "example.com"
5533 hapd = hostapd.add_ap(apdev[0], params)
5534
5535 bssid2 = apdev[1]['bssid']
5536 params = hs20_ap_params(ssid="test-hs20-other")
5537 params['hessid'] = bssid2
5538 params['nai_realm'] = [ "0,example.org,13[5:6],21[2:4][5:7]" ]
5539 params['domain_name'] = "example.org"
5540 hapd2 = hostapd.add_ap(apdev[1], params)
5541
5542 dev[0].hs20_enable()
5543 dev[0].scan_for_bss(bssid2, freq="2412")
5544 dev[0].scan_for_bss(bssid, freq="2412")
5545 id = dev[0].add_cred_values({ 'realm': "example.com",
5546 'priority': '2',
5547 'username': "hs20-test",
5548 'password': "password",
5549 'domain': "example.com" })
5550 id2 = dev[0].add_cred_values({ 'realm': "example.org",
5551 'priority': '3',
5552 'username': "hs20-test",
5553 'password': "password",
5554 'domain': "example.org" })
5555 dev[0].request("INTERWORKING_SELECT auto freq=2412")
5556 ev = dev[0].wait_connected(timeout=15)
5557 if bssid2 not in ev:
5558 raise Exception("Connected to incorrect network")
5559
5560 def test_ap_hs20_anqp_invalid_gas_response(dev, apdev):
5561 """Hotspot 2.0 network selection and invalid GAS response"""
5562 bssid = apdev[0]['bssid']
5563 params = hs20_ap_params()
5564 params['hessid'] = bssid
5565 hapd = hostapd.add_ap(apdev[0], params)
5566
5567 dev[0].scan_for_bss(bssid, freq="2412")
5568 hapd.set("ext_mgmt_frame_handling", "1")
5569
5570 dev[0].hs20_enable()
5571
5572 id = dev[0].add_cred_values({ 'realm': "example.com",
5573 'username': "test",
5574 'password': "secret",
5575 'domain': "example.com",
5576 'roaming_consortium': "112234",
5577 'eap': 'TTLS' })
5578 dev[0].request("INTERWORKING_SELECT freq=2412")
5579
5580 query = gas_rx(hapd)
5581 gas = parse_gas(query['payload'])
5582
5583 logger.info("ANQP: Unexpected Advertisement Protocol in response")
5584 resp = action_response(query)
5585 adv_proto = struct.pack('8B', 108, 6, 127, 0xdd, 0x00, 0x11, 0x22, 0x33)
5586 data = struct.pack('<H', 0)
5587 resp['payload'] = struct.pack('<BBBHH', ACTION_CATEG_PUBLIC,
5588 GAS_INITIAL_RESPONSE,
5589 gas['dialog_token'], 0, 0) + adv_proto + data
5590 send_gas_resp(hapd, resp)
5591
5592 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
5593 if ev is None:
5594 raise Exception("No ANQP-QUERY-DONE seen")
5595 if "result=INVALID_FRAME" not in ev:
5596 raise Exception("Unexpected result: " + ev)
5597
5598 dev[0].request("INTERWORKING_SELECT freq=2412")
5599
5600 query = gas_rx(hapd)
5601 gas = parse_gas(query['payload'])
5602
5603 logger.info("ANQP: Invalid element length for Info ID 1234")
5604 resp = action_response(query)
5605 adv_proto = struct.pack('BBBB', 108, 2, 127, 0)
5606 elements = struct.pack('<HH', 1234, 1)
5607 data = struct.pack('<H', len(elements)) + elements
5608 resp['payload'] = struct.pack('<BBBHH', ACTION_CATEG_PUBLIC,
5609 GAS_INITIAL_RESPONSE,
5610 gas['dialog_token'], 0, 0) + adv_proto + data
5611 send_gas_resp(hapd, resp)
5612
5613 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
5614 if ev is None:
5615 raise Exception("No ANQP-QUERY-DONE seen")
5616 if "result=INVALID_FRAME" not in ev:
5617 raise Exception("Unexpected result: " + ev)
5618
5619 with alloc_fail(dev[0], 1, "=anqp_add_extra"):
5620 dev[0].request("INTERWORKING_SELECT freq=2412")
5621
5622 query = gas_rx(hapd)
5623 gas = parse_gas(query['payload'])
5624
5625 resp = action_response(query)
5626 elements = struct.pack('<HHHH', 1, 0, 1, 0)
5627 data = struct.pack('<H', len(elements)) + elements
5628 resp['payload'] = struct.pack('<BBBHH', ACTION_CATEG_PUBLIC,
5629 GAS_INITIAL_RESPONSE,
5630 gas['dialog_token'], 0, 0) + adv_proto + data
5631 send_gas_resp(hapd, resp)
5632
5633 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
5634 if ev is None:
5635 raise Exception("No ANQP-QUERY-DONE seen")
5636 if "result=SUCCESS" not in ev:
5637 raise Exception("Unexpected result: " + ev)
5638
5639 with alloc_fail(dev[0], 1, "wpabuf_alloc_copy;anqp_add_extra"):
5640 dev[0].request("INTERWORKING_SELECT freq=2412")
5641
5642 query = gas_rx(hapd)
5643 gas = parse_gas(query['payload'])
5644
5645 resp = action_response(query)
5646 elements = struct.pack('<HHHH', 1, 0, 1, 0)
5647 data = struct.pack('<H', len(elements)) + elements
5648 resp['payload'] = struct.pack('<BBBHH', ACTION_CATEG_PUBLIC,
5649 GAS_INITIAL_RESPONSE,
5650 gas['dialog_token'], 0, 0) + adv_proto + data
5651 send_gas_resp(hapd, resp)
5652
5653 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
5654 if ev is None:
5655 raise Exception("No ANQP-QUERY-DONE seen")
5656 if "result=SUCCESS" not in ev:
5657 raise Exception("Unexpected result: " + ev)
5658
5659 tests = [ struct.pack('<HH', 0xdddd, 0),
5660 struct.pack('<HH3B', 0xdddd, 3, 0x50, 0x6f, 0x9a),
5661 struct.pack('<HH4B', 0xdddd, 4, 0x50, 0x6f, 0x9a, 0),
5662 struct.pack('<HH4B', 0xdddd, 4, 0x11, 0x22, 0x33, 0),
5663 struct.pack('<HHHH', 1, 0, 1, 0) ]
5664 for elements in tests:
5665 dev[0].request("INTERWORKING_SELECT freq=2412")
5666
5667 query = gas_rx(hapd)
5668 gas = parse_gas(query['payload'])
5669
5670 resp = action_response(query)
5671 data = struct.pack('<H', len(elements)) + elements
5672 resp['payload'] = struct.pack('<BBBHH', ACTION_CATEG_PUBLIC,
5673 GAS_INITIAL_RESPONSE,
5674 gas['dialog_token'], 0, 0) + adv_proto + data
5675 send_gas_resp(hapd, resp)
5676
5677 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
5678 if ev is None:
5679 raise Exception("No ANQP-QUERY-DONE seen")
5680 if "result=SUCCESS" not in ev:
5681 raise Exception("Unexpected result: " + ev)
5682
5683 def test_ap_hs20_set_profile_failures(dev, apdev):
5684 """Hotspot 2.0 and failures during profile configuration"""
5685 bssid = apdev[0]['bssid']
5686 params = hs20_ap_params()
5687 params['hessid'] = bssid
5688 params['anqp_3gpp_cell_net'] = "555,444"
5689 hapd = hostapd.add_ap(apdev[0], params)
5690
5691 dev[0].hs20_enable()
5692 dev[0].scan_for_bss(bssid, freq="2412")
5693
5694 id = dev[0].add_cred_values({ 'realm': "example.com",
5695 'domain': "example.com",
5696 'username': "test",
5697 'password': "secret",
5698 'eap': 'TTLS' })
5699 interworking_select(dev[0], bssid, "home", freq=2412)
5700 dev[0].dump_monitor()
5701 dev[0].request("NOTE ssid->eap.eap_methods = os_malloc()")
5702 with alloc_fail(dev[0], 1, "interworking_set_eap_params"):
5703 dev[0].request("INTERWORKING_CONNECT " + bssid)
5704 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5705 dev[0].remove_cred(id)
5706
5707 id = dev[0].add_cred_values({ 'realm': "example.com",
5708 'domain': "example.com",
5709 'username': "hs20-test-with-domain@example.com",
5710 'password': "password" })
5711 interworking_select(dev[0], bssid, "home", freq=2412)
5712 dev[0].dump_monitor()
5713 dev[0].request("NOTE anon = os_malloc()")
5714 with alloc_fail(dev[0], 1, "interworking_set_eap_params"):
5715 dev[0].request("INTERWORKING_CONNECT " + bssid)
5716 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5717 dev[0].request("NOTE Successful connection with cred->username including realm")
5718 dev[0].request("INTERWORKING_CONNECT " + bssid)
5719 dev[0].wait_connected()
5720 dev[0].remove_cred(id)
5721 dev[0].wait_disconnected()
5722
5723 id = dev[0].add_cred_values({ 'realm': "example.com",
5724 'domain': "example.com",
5725 'username': "hs20-test",
5726 'password': "password" })
5727 interworking_select(dev[0], bssid, "home", freq=2412)
5728 dev[0].dump_monitor()
5729 dev[0].request("NOTE anon = os_malloc() (second)")
5730 with alloc_fail(dev[0], 1, "interworking_set_eap_params"):
5731 dev[0].request("INTERWORKING_CONNECT " + bssid)
5732 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5733 with alloc_fail(dev[0], 1, "wpa_config_add_network;interworking_connect"):
5734 dev[0].request("INTERWORKING_CONNECT " + bssid)
5735 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5736 with alloc_fail(dev[0], 1, "=interworking_connect"):
5737 dev[0].request("INTERWORKING_CONNECT " + bssid)
5738 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5739 dev[0].request("NOTE wpa_config_set(eap)")
5740 with alloc_fail(dev[0], 1, "wpa_config_parse_eap;wpa_config_set;interworking_connect"):
5741 dev[0].request("INTERWORKING_CONNECT " + bssid)
5742 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5743 dev[0].request("NOTE wpa_config_set(TTLS-NON_EAP_MSCHAPV2-phase2)")
5744 with alloc_fail(dev[0], 1, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
5745 dev[0].request("INTERWORKING_CONNECT " + bssid)
5746 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5747 dev[0].remove_cred(id)
5748
5749 id = dev[0].add_cred_values({ 'roaming_consortium': "112233",
5750 'domain': "example.com",
5751 'username': "hs20-test",
5752 'password': "password",
5753 'eap': 'TTLS',
5754 'phase2': "auth=MSCHAPV2" })
5755 interworking_select(dev[0], bssid, "home", freq=2412)
5756 dev[0].dump_monitor()
5757 dev[0].request("NOTE anon = os_strdup()")
5758 with alloc_fail(dev[0], 2, "interworking_set_eap_params"):
5759 dev[0].request("INTERWORKING_CONNECT " + bssid)
5760 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5761 dev[0].request("NOTE wpa_config_set_quoted(anonymous_identity)")
5762 with alloc_fail(dev[0], 1, "=wpa_config_set_quoted;interworking_set_eap_params"):
5763 dev[0].request("INTERWORKING_CONNECT " + bssid)
5764 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5765 dev[0].request("NOTE Successful connection with cred->realm not included")
5766 dev[0].request("INTERWORKING_CONNECT " + bssid)
5767 dev[0].wait_connected()
5768 dev[0].remove_cred(id)
5769 dev[0].wait_disconnected()
5770
5771 id = dev[0].add_cred_values({ 'roaming_consortium': "112233",
5772 'domain': "example.com",
5773 'realm': "example.com",
5774 'username': "user",
5775 'password': "password",
5776 'eap': 'PEAP' })
5777 interworking_select(dev[0], bssid, "home", freq=2412)
5778 dev[0].dump_monitor()
5779 dev[0].request("NOTE id = os_strdup()")
5780 with alloc_fail(dev[0], 2, "interworking_set_eap_params"):
5781 dev[0].request("INTERWORKING_CONNECT " + bssid)
5782 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5783 dev[0].request("NOTE wpa_config_set_quoted(identity)")
5784 with alloc_fail(dev[0], 1, "=wpa_config_set_quoted;interworking_set_eap_params"):
5785 dev[0].request("INTERWORKING_CONNECT " + bssid)
5786 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5787 dev[0].remove_cred(id)
5788
5789 id = dev[0].add_cred_values({ 'roaming_consortium': "112233",
5790 'domain': "example.com",
5791 'realm': "example.com",
5792 'username': "user",
5793 'password': "password",
5794 'eap': "TTLS" })
5795 interworking_select(dev[0], bssid, "home", freq=2412)
5796 dev[0].dump_monitor()
5797 dev[0].request("NOTE wpa_config_set_quoted(identity) (second)")
5798 with alloc_fail(dev[0], 2, "=wpa_config_set_quoted;interworking_set_eap_params"):
5799 dev[0].request("INTERWORKING_CONNECT " + bssid)
5800 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5801 dev[0].request("NOTE wpa_config_set_quoted(password)")
5802 with alloc_fail(dev[0], 3, "=wpa_config_set_quoted;interworking_set_eap_params"):
5803 dev[0].request("INTERWORKING_CONNECT " + bssid)
5804 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5805 with alloc_fail(dev[0], 1, "wpa_config_add_network;interworking_connect_roaming_consortium"):
5806 dev[0].request("INTERWORKING_CONNECT " + bssid)
5807 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5808 with alloc_fail(dev[0], 1, "=interworking_connect_roaming_consortium"):
5809 dev[0].request("INTERWORKING_CONNECT " + bssid)
5810 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5811 dev[0].remove_cred(id)
5812
5813 id = dev[0].add_cred_values({ 'roaming_consortium': "112233",
5814 'domain': "example.com",
5815 'realm': "example.com",
5816 'username': "user",
5817 'eap': "PEAP" })
5818 dev[0].set_cred(id, "password", "ext:password");
5819 interworking_select(dev[0], bssid, "home", freq=2412)
5820 dev[0].dump_monitor()
5821 dev[0].request("NOTE wpa_config_set(password)")
5822 with alloc_fail(dev[0], 3, "wpa_config_set;interworking_set_eap_params"):
5823 dev[0].request("INTERWORKING_CONNECT " + bssid)
5824 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5825 with alloc_fail(dev[0], 1, "interworking_set_hs20_params"):
5826 dev[0].request("INTERWORKING_CONNECT " + bssid)
5827 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5828 dev[0].remove_cred(id)
5829
5830 id = dev[0].add_cred_values({ 'realm': "example.com",
5831 'domain': "example.com",
5832 'username': "certificate-user",
5833 'phase1': "include_tls_length=0",
5834 'domain_suffix_match': "example.com",
5835 'ca_cert': "auth_serv/ca.pem",
5836 'client_cert': "auth_serv/user.pem",
5837 'private_key': "auth_serv/user.key",
5838 'private_key_passwd': "secret" })
5839 interworking_select(dev[0], bssid, "home", freq=2412)
5840 dev[0].dump_monitor()
5841 dev[0].request("NOTE wpa_config_set_quoted(client_cert)")
5842 with alloc_fail(dev[0], 2, "=wpa_config_set_quoted;interworking_set_eap_params"):
5843 dev[0].request("INTERWORKING_CONNECT " + bssid)
5844 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5845 dev[0].request("NOTE wpa_config_set_quoted(private_key)")
5846 with alloc_fail(dev[0], 3, "=wpa_config_set_quoted;interworking_set_eap_params"):
5847 dev[0].request("INTERWORKING_CONNECT " + bssid)
5848 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5849 dev[0].request("NOTE wpa_config_set_quoted(private_key_passwd)")
5850 with alloc_fail(dev[0], 4, "=wpa_config_set_quoted;interworking_set_eap_params"):
5851 dev[0].request("INTERWORKING_CONNECT " + bssid)
5852 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5853 dev[0].request("NOTE wpa_config_set_quoted(ca_cert)")
5854 with alloc_fail(dev[0], 5, "=wpa_config_set_quoted;interworking_set_eap_params"):
5855 dev[0].request("INTERWORKING_CONNECT " + bssid)
5856 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5857 dev[0].request("NOTE wpa_config_set_quoted(domain_suffix_match)")
5858 with alloc_fail(dev[0], 6, "=wpa_config_set_quoted;interworking_set_eap_params"):
5859 dev[0].request("INTERWORKING_CONNECT " + bssid)
5860 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5861 with alloc_fail(dev[0], 1, "interworking_set_hs20_params"):
5862 dev[0].request("INTERWORKING_CONNECT " + bssid)
5863 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5864 dev[0].remove_cred(id)
5865
5866 id = dev[0].add_cred_values({ 'imsi': "555444-333222111", 'eap': "SIM",
5867 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"})
5868 interworking_select(dev[0], bssid, freq=2412)
5869 dev[0].dump_monitor()
5870 with alloc_fail(dev[0], 1, "interworking_set_hs20_params"):
5871 dev[0].request("INTERWORKING_CONNECT " + bssid)
5872 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5873 dev[0].request("NOTE wpa_config_set_quoted(password;milenage)")
5874 with alloc_fail(dev[0], 2, "=wpa_config_set_quoted;interworking_connect_3gpp"):
5875 dev[0].request("INTERWORKING_CONNECT " + bssid)
5876 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5877 dev[0].request("NOTE wpa_config_set(eap)")
5878 with alloc_fail(dev[0], 1, "wpa_config_parse_eap;wpa_config_set;interworking_connect_3gpp"):
5879 dev[0].request("INTERWORKING_CONNECT " + bssid)
5880 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5881 dev[0].request("NOTE set_root_nai:wpa_config_set(identity)")
5882 with alloc_fail(dev[0], 1, "wpa_config_parse_str;interworking_connect_3gpp"):
5883 dev[0].request("INTERWORKING_CONNECT " + bssid)
5884 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5885 dev[0].remove_cred(id)
5886
5887 id = dev[0].add_cred_values({ 'roaming_consortium': "112233",
5888 'username': "user@example.com",
5889 'password': "password" })
5890 interworking_select(dev[0], bssid, freq=2412)
5891 dev[0].dump_monitor()
5892 dev[0].request("NOTE Interworking: No EAP method set for credential using roaming consortium")
5893 dev[0].request("INTERWORKING_CONNECT " + bssid)
5894 dev[0].remove_cred(id)
5895
5896 hapd.disable()
5897 params = hs20_ap_params()
5898 params['nai_realm'] = "0,example.com,25[3:26]"
5899 hapd = hostapd.add_ap(apdev[0], params)
5900 id = dev[0].add_cred_values({ 'realm': "example.com",
5901 'domain': "example.com",
5902 'username': "hs20-test",
5903 'password': "password" })
5904 interworking_select(dev[0], bssid, freq=2412)
5905 dev[0].dump_monitor()
5906 dev[0].request("NOTE wpa_config_set(PEAP/FAST-phase1)")
5907 with alloc_fail(dev[0], 1, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
5908 dev[0].request("INTERWORKING_CONNECT " + bssid)
5909 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5910 dev[0].request("NOTE wpa_config_set(PEAP/FAST-pac_interworking)")
5911 with alloc_fail(dev[0], 2, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
5912 dev[0].request("INTERWORKING_CONNECT " + bssid)
5913 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5914 dev[0].request("NOTE wpa_config_set(PEAP/FAST-phase2)")
5915 with alloc_fail(dev[0], 3, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
5916 dev[0].request("INTERWORKING_CONNECT " + bssid)
5917 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5918
5919 hapd.disable()
5920 params = hs20_ap_params()
5921 params['nai_realm'] = "0,example.com,21"
5922 hapd = hostapd.add_ap(apdev[0], params)
5923 interworking_select(dev[0], bssid, freq=2412)
5924 dev[0].request("NOTE wpa_config_set(TTLS-defaults-phase2)")
5925 with alloc_fail(dev[0], 1, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
5926 dev[0].request("INTERWORKING_CONNECT " + bssid)
5927 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5928
5929 hapd.disable()
5930 params = hs20_ap_params()
5931 params['nai_realm'] = "0,example.com,21[2:3]"
5932 hapd = hostapd.add_ap(apdev[0], params)
5933 interworking_select(dev[0], bssid, freq=2412)
5934 dev[0].request("NOTE wpa_config_set(TTLS-NON_EAP_MSCHAP-phase2)")
5935 with alloc_fail(dev[0], 1, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
5936 dev[0].request("INTERWORKING_CONNECT " + bssid)
5937 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5938
5939 hapd.disable()
5940 params = hs20_ap_params()
5941 params['nai_realm'] = "0,example.com,21[2:2]"
5942 hapd = hostapd.add_ap(apdev[0], params)
5943 interworking_select(dev[0], bssid, freq=2412)
5944 dev[0].request("NOTE wpa_config_set(TTLS-NON_EAP_CHAP-phase2)")
5945 with alloc_fail(dev[0], 1, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
5946 dev[0].request("INTERWORKING_CONNECT " + bssid)
5947 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5948
5949 hapd.disable()
5950 params = hs20_ap_params()
5951 params['nai_realm'] = "0,example.com,21[2:1]"
5952 hapd = hostapd.add_ap(apdev[0], params)
5953 interworking_select(dev[0], bssid, freq=2412)
5954 dev[0].request("NOTE wpa_config_set(TTLS-NON_EAP_PAP-phase2)")
5955 with alloc_fail(dev[0], 1, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
5956 dev[0].request("INTERWORKING_CONNECT " + bssid)
5957 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5958
5959 hapd.disable()
5960 params = hs20_ap_params()
5961 params['nai_realm'] = "0,example.com,21[3:26]"
5962 hapd = hostapd.add_ap(apdev[0], params)
5963 interworking_select(dev[0], bssid, freq=2412)
5964 dev[0].request("NOTE wpa_config_set(TTLS-EAP-MSCHAPV2-phase2)")
5965 with alloc_fail(dev[0], 1, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
5966 dev[0].request("INTERWORKING_CONNECT " + bssid)
5967 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5968
5969 dev[0].remove_cred(id)
5970
5971 def test_ap_hs20_unexpected(dev, apdev):
5972 """Unexpected Hotspot 2.0 AP configuration"""
5973 check_eap_capa(dev[0], "MSCHAPV2")
5974 bssid = apdev[0]['bssid']
5975 params = hostapd.wpa_eap_params(ssid="test-hs20-fake")
5976 params['wpa'] = "3"
5977 params['wpa_pairwise'] = "TKIP CCMP"
5978 params['rsn_pairwise'] = "CCMP"
5979 params['ieee80211w'] = "1"
5980 #params['vendor_elements'] = 'dd07506f9a10140000'
5981 params['vendor_elements'] = 'dd04506f9a10'
5982 hostapd.add_ap(apdev[0], params)
5983
5984 dev[0].hs20_enable()
5985 dev[0].scan_for_bss(bssid, freq="2412")
5986 dev[0].connect("test-hs20-fake", key_mgmt="WPA-EAP", eap="TTLS",
5987 pairwise="TKIP",
5988 identity="hs20-test", password="password",
5989 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
5990 scan_freq="2412")
5991
5992 dev[1].hs20_enable()
5993 dev[1].scan_for_bss(bssid, freq="2412")
5994 dev[1].connect("test-hs20-fake", key_mgmt="WPA-EAP", eap="TTLS",
5995 proto="WPA",
5996 identity="hs20-test", password="password",
5997 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
5998 scan_freq="2412")
5999
6000 dev[2].hs20_enable()
6001 dev[2].scan_for_bss(bssid, freq="2412")
6002 dev[2].connect("test-hs20-fake", key_mgmt="WPA-EAP", eap="TTLS",
6003 ieee80211w="1",
6004 proto="RSN", pairwise="CCMP",
6005 identity="hs20-test", password="password",
6006 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
6007 scan_freq="2412")
6008
6009 def test_ap_interworking_element_update(dev, apdev):
6010 """Dynamic Interworking element update"""
6011 bssid = apdev[0]['bssid']
6012 params = hs20_ap_params()
6013 params['hessid'] = bssid
6014 hapd = hostapd.add_ap(apdev[0], params)
6015
6016 dev[0].hs20_enable()
6017 dev[0].scan_for_bss(bssid, freq="2412")
6018 bss = dev[0].get_bss(bssid)
6019 logger.info("Before update: " + str(bss))
6020 if '6b091e0701020000000300' not in bss['ie']:
6021 raise Exception("Expected Interworking element not seen before update")
6022
6023 # Update configuration parameters related to Interworking element
6024 hapd.set('access_network_type', '2')
6025 hapd.set('asra', '1')
6026 hapd.set('esr', '1')
6027 hapd.set('uesa', '1')
6028 hapd.set('venue_group', '2')
6029 hapd.set('venue_type', '8')
6030 if "OK" not in hapd.request("UPDATE_BEACON"):
6031 raise Exception("UPDATE_BEACON failed")
6032 dev[0].request("BSS_FLUSH 0")
6033 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
6034 bss = dev[0].get_bss(bssid)
6035 logger.info("After update: " + str(bss))
6036 if '6b09f20208020000000300' not in bss['ie']:
6037 raise Exception("Expected Interworking element not seen after update")
6038
6039 def test_ap_hs20_terms_and_conditions(dev, apdev):
6040 """Hotspot 2.0 Terms and Conditions signaling"""
6041 check_eap_capa(dev[0], "MSCHAPV2")
6042 bssid = apdev[0]['bssid']
6043 params = hs20_ap_params()
6044 params['hessid'] = bssid
6045 params['hs20_t_c_filename'] = 'terms-and-conditions'
6046 params['hs20_t_c_timestamp'] = '123456789'
6047
6048 hostapd.add_ap(apdev[0], params)
6049
6050 dev[0].hs20_enable()
6051 dev[0].connect("test-hs20", proto="RSN", key_mgmt="WPA-EAP", eap="TTLS",
6052 identity="hs20-t-c-test", password="password",
6053 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
6054 ieee80211w='2', scan_freq="2412")
6055 ev = dev[0].wait_event(["HS20-T-C-ACCEPTANCE"], timeout=5)
6056 if ev is None:
6057 raise Exception("Terms and Conditions Acceptance notification not received")
6058 url = "https://example.com/t_and_c?addr=%s&ap=123" % dev[0].own_addr()
6059 if url not in ev:
6060 raise Exception("Unexpected URL: " + ev)
6061
6062 def test_ap_hs20_terms_and_conditions_coa(dev, apdev):
6063 """Hotspot 2.0 Terms and Conditions signaling - CoA"""
6064 try:
6065 import pyrad.client
6066 import pyrad.packet
6067 import pyrad.dictionary
6068 import radius_das
6069 except ImportError:
6070 raise HwsimSkip("No pyrad modules available")
6071
6072 check_eap_capa(dev[0], "MSCHAPV2")
6073 bssid = apdev[0]['bssid']
6074 params = hs20_ap_params()
6075 params['hessid'] = bssid
6076 params['hs20_t_c_filename'] = 'terms-and-conditions'
6077 params['hs20_t_c_timestamp'] = '123456789'
6078 params['own_ip_addr'] = "127.0.0.1"
6079 params['radius_das_port'] = "3799"
6080 params['radius_das_client'] = "127.0.0.1 secret"
6081 params['radius_das_require_event_timestamp'] = "1"
6082 hapd = hostapd.add_ap(apdev[0], params)
6083
6084 dev[0].hs20_enable()
6085 dev[0].connect("test-hs20", proto="RSN", key_mgmt="WPA-EAP", eap="TTLS",
6086 identity="hs20-t-c-test", password="password",
6087 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
6088 ieee80211w='2', scan_freq="2412")
6089
6090 ev = hapd.wait_event(["HS20-T-C-FILTERING-ADD"], timeout=5)
6091 if ev is None:
6092 raise Exception("Terms and Conditions filtering not enabled")
6093 if ev.split(' ')[1] != dev[0].own_addr():
6094 raise Exception("Unexpected STA address for filtering: " + ev)
6095
6096 ev = dev[0].wait_event(["HS20-T-C-ACCEPTANCE"], timeout=5)
6097 if ev is None:
6098 raise Exception("Terms and Conditions Acceptance notification not received")
6099 url = "https://example.com/t_and_c?addr=%s&ap=123" % dev[0].own_addr()
6100 if url not in ev:
6101 raise Exception("Unexpected URL: " + ev)
6102
6103 dict = pyrad.dictionary.Dictionary("dictionary.radius")
6104
6105 srv = pyrad.client.Client(server="127.0.0.1", acctport=3799,
6106 secret="secret", dict=dict)
6107 srv.retries = 1
6108 srv.timeout = 1
6109
6110 sta = hapd.get_sta(dev[0].own_addr())
6111 multi_sess_id = sta['authMultiSessionId']
6112
6113 logger.info("CoA-Request with matching Acct-Session-Id")
6114 vsa = binascii.unhexlify('00009f68090600000000')
6115 req = radius_das.CoAPacket(dict=dict, secret="secret",
6116 NAS_IP_Address="127.0.0.1",
6117 Acct_Multi_Session_Id=multi_sess_id,
6118 Chargeable_User_Identity="hs20-cui",
6119 Event_Timestamp=int(time.time()),
6120 Vendor_Specific=vsa)
6121 reply = srv.SendPacket(req)
6122 logger.debug("RADIUS response from hostapd")
6123 for i in reply.keys():
6124 logger.debug("%s: %s" % (i, reply[i]))
6125 if reply.code != pyrad.packet.CoAACK:
6126 raise Exception("CoA-Request failed")
6127
6128 ev = hapd.wait_event(["HS20-T-C-FILTERING-REMOVE"], timeout=5)
6129 if ev is None:
6130 raise Exception("Terms and Conditions filtering not disabled")
6131 if ev.split(' ')[1] != dev[0].own_addr():
6132 raise Exception("Unexpected STA address for filtering: " + ev)
6133
6134 def test_ap_hs20_terms_and_conditions_sql(dev, apdev, params):
6135 """Hotspot 2.0 Terms and Conditions using SQLite for user DB"""
6136 addr = dev[0].own_addr()
6137 run_ap_hs20_terms_and_conditions_sql(dev, apdev, params,
6138 "https://example.com/t_and_c?addr=@1@&ap=123",
6139 "https://example.com/t_and_c?addr=" + addr + "&ap=123")
6140
6141 def test_ap_hs20_terms_and_conditions_sql2(dev, apdev, params):
6142 """Hotspot 2.0 Terms and Conditions using SQLite for user DB"""
6143 addr = dev[0].own_addr()
6144 run_ap_hs20_terms_and_conditions_sql(dev, apdev, params,
6145 "https://example.com/t_and_c?addr=@1@",
6146 "https://example.com/t_and_c?addr=" + addr)
6147
6148 def run_ap_hs20_terms_and_conditions_sql(dev, apdev, params, url_template,
6149 url_expected):
6150 check_eap_capa(dev[0], "MSCHAPV2")
6151 try:
6152 import sqlite3
6153 except ImportError:
6154 raise HwsimSkip("No sqlite3 module available")
6155 dbfile = os.path.join(params['logdir'], "eap-user.db")
6156 try:
6157 os.remove(dbfile)
6158 except:
6159 pass
6160 con = sqlite3.connect(dbfile)
6161 with con:
6162 cur = con.cursor()
6163 cur.execute("CREATE TABLE users(identity TEXT PRIMARY KEY, methods TEXT, password TEXT, remediation TEXT, phase2 INTEGER, t_c_timestamp INTEGER)")
6164 cur.execute("CREATE TABLE wildcards(identity TEXT PRIMARY KEY, methods TEXT)")
6165 cur.execute("INSERT INTO users(identity,methods,password,phase2) VALUES ('user-mschapv2','TTLS-MSCHAPV2','password',1)")
6166 cur.execute("INSERT INTO wildcards(identity,methods) VALUES ('','TTLS,TLS')")
6167 cur.execute("CREATE TABLE authlog(timestamp TEXT, session TEXT, nas_ip TEXT, username TEXT, note TEXT)")
6168 cur.execute("CREATE TABLE pending_tc(mac_addr TEXT PRIMARY KEY, identity TEXT)")
6169 cur.execute("CREATE TABLE current_sessions(mac_addr TEXT PRIMARY KEY, identity TEXT, start_time TEXT, nas TEXT, hs20_t_c_filtering BOOLEAN, waiting_coa_ack BOOLEAN, coa_ack_received BOOLEAN)")
6170
6171
6172 try:
6173 params = { "ssid": "as", "beacon_int": "2000",
6174 "radius_server_clients": "auth_serv/radius_clients.conf",
6175 "radius_server_auth_port": '18128',
6176 "eap_server": "1",
6177 "eap_user_file": "sqlite:" + dbfile,
6178 "ca_cert": "auth_serv/ca.pem",
6179 "server_cert": "auth_serv/server.pem",
6180 "private_key": "auth_serv/server.key" }
6181 params['hs20_t_c_server_url'] = url_template
6182 authsrv = hostapd.add_ap(apdev[1], params)
6183
6184 bssid = apdev[0]['bssid']
6185 params = hs20_ap_params()
6186 params['auth_server_port'] = "18128"
6187 params['hs20_t_c_filename'] = 'terms-and-conditions'
6188 params['hs20_t_c_timestamp'] = '123456789'
6189 params['own_ip_addr'] = "127.0.0.1"
6190 params['radius_das_port'] = "3799"
6191 params['radius_das_client'] = "127.0.0.1 radius"
6192 params['radius_das_require_event_timestamp'] = "1"
6193 params['disable_pmksa_caching'] = '1'
6194 hapd = hostapd.add_ap(apdev[0], params)
6195
6196 dev[0].request("SET pmf 1")
6197 dev[0].hs20_enable()
6198 id = dev[0].add_cred_values({ 'realm': "example.com",
6199 'username': "user-mschapv2",
6200 'password': "password",
6201 'ca_cert': "auth_serv/ca.pem" })
6202 interworking_select(dev[0], bssid, freq="2412")
6203 interworking_connect(dev[0], bssid, "TTLS")
6204
6205 ev = hapd.wait_event(["HS20-T-C-FILTERING-ADD"], timeout=5)
6206 if ev is None:
6207 raise Exception("Terms and Conditions filtering not enabled")
6208 hapd.dump_monitor()
6209
6210 ev = dev[0].wait_event(["HS20-T-C-ACCEPTANCE"], timeout=5)
6211 if ev is None:
6212 raise Exception("Terms and Conditions Acceptance notification not received")
6213 url = ev.split(' ')[1]
6214 if url != url_expected:
6215 raise Exception("Unexpected URL delivered to the client: %s (expected %s)" % (url, url_expected))
6216 dev[0].dump_monitor()
6217
6218 with con:
6219 cur = con.cursor()
6220 cur.execute("SELECT * from current_sessions")
6221 rows = cur.fetchall()
6222 if len(rows) != 1:
6223 raise Exeception("Unexpected number of rows in current_sessions (%d; expected %d)" % (len(rows), 1))
6224 logger.info("current_sessions: " + str(rows))
6225
6226 if "OK" not in authsrv.request("DAC_REQUEST coa %s t_c_clear" % dev[0].own_addr()):
6227 raise Exception("DAC_REQUEST failed")
6228
6229 ev = hapd.wait_event(["HS20-T-C-FILTERING-REMOVE"], timeout=5)
6230 if ev is None:
6231 raise Exception("Terms and Conditions filtering not disabled")
6232 if ev.split(' ')[1] != dev[0].own_addr():
6233 raise Exception("Unexpected STA address for filtering: " + ev)
6234
6235 time.sleep(0.2)
6236 with con:
6237 cur = con.cursor()
6238 cur.execute("SELECT * from current_sessions")
6239 rows = cur.fetchall()
6240 if len(rows) != 1:
6241 raise Exeception("Unexpected number of rows in current_sessions (%d; expected %d)" % (len(rows), 1))
6242 logger.info("current_sessions: " + str(rows))
6243 if rows[0][4] != 0 or rows[0][5] != 0 or rows[0][6] != 1:
6244 raise Exception("Unexpected current_sessions information after CoA-ACK")
6245
6246 dev[0].request("DISCONNECT")
6247 dev[0].wait_disconnected()
6248 dev[0].dump_monitor()
6249
6250 # Simulate T&C server operation on user reading the updated version
6251 with con:
6252 cur = con.cursor()
6253 cur.execute("SELECT identity FROM pending_tc WHERE mac_addr='" +
6254 dev[0].own_addr() + "'")
6255 rows = cur.fetchall()
6256 if len(rows) != 1:
6257 raise Exception("No pending_tc entry found")
6258 if rows[0][0] != 'user-mschapv2':
6259 raise Exception("Unexpected pending_tc identity value")
6260
6261 cur.execute("UPDATE users SET t_c_timestamp=123456789 WHERE identity='user-mschapv2'")
6262
6263 dev[0].request("RECONNECT")
6264 dev[0].wait_connected()
6265
6266 ev = hapd.wait_event(["HS20-T-C-FILTERING-ADD"], timeout=0.1)
6267 if ev is not None:
6268 raise Exception("Terms and Conditions filtering enabled unexpectedly")
6269 hapd.dump_monitor()
6270
6271 ev = dev[0].wait_event(["HS20-T-C-ACCEPTANCE"], timeout=0.1)
6272 if ev is not None:
6273 raise Exception("Unexpected Terms and Conditions Acceptance notification")
6274 dev[0].dump_monitor()
6275
6276 dev[0].request("DISCONNECT")
6277 dev[0].wait_disconnected()
6278 dev[0].dump_monitor()
6279
6280 # New T&C available
6281 hapd.set('hs20_t_c_timestamp', '123456790')
6282
6283 dev[0].request("RECONNECT")
6284 dev[0].wait_connected()
6285
6286 ev = hapd.wait_event(["HS20-T-C-FILTERING-ADD"], timeout=5)
6287 if ev is None:
6288 raise Exception("Terms and Conditions filtering not enabled")
6289 hapd.dump_monitor()
6290
6291 ev = dev[0].wait_event(["HS20-T-C-ACCEPTANCE"], timeout=5)
6292 if ev is None:
6293 raise Exception("Terms and Conditions Acceptance notification not received (2)")
6294 dev[0].dump_monitor()
6295
6296 dev[0].request("DISCONNECT")
6297 dev[0].wait_disconnected()
6298 dev[0].dump_monitor()
6299
6300 # Simulate T&C server operation on user reading the updated version
6301 with con:
6302 cur = con.cursor()
6303 cur.execute("UPDATE users SET t_c_timestamp=123456790 WHERE identity='user-mschapv2'")
6304
6305 dev[0].request("RECONNECT")
6306 dev[0].wait_connected()
6307
6308 ev = hapd.wait_event(["HS20-T-C-FILTERING-ADD"], timeout=0.1)
6309 if ev is not None:
6310 raise Exception("Terms and Conditions filtering enabled unexpectedly")
6311 hapd.dump_monitor()
6312
6313 ev = dev[0].wait_event(["HS20-T-C-ACCEPTANCE"], timeout=0.1)
6314 if ev is not None:
6315 raise Exception("Unexpected Terms and Conditions Acceptance notification (2)")
6316 dev[0].dump_monitor()
6317 finally:
6318 os.remove(dbfile)
6319 dev[0].request("SET pmf 0")
6320
6321 def test_ap_hs20_release_number_1(dev, apdev):
6322 """Hotspot 2.0 with AP claiming support for Release 1"""
6323 run_ap_hs20_release_number(dev, apdev, 1)
6324
6325 def test_ap_hs20_release_number_2(dev, apdev):
6326 """Hotspot 2.0 with AP claiming support for Release 2"""
6327 run_ap_hs20_release_number(dev, apdev, 2)
6328
6329 def test_ap_hs20_release_number_3(dev, apdev):
6330 """Hotspot 2.0 with AP claiming support for Release 3"""
6331 run_ap_hs20_release_number(dev, apdev, 3)
6332
6333 def run_ap_hs20_release_number(dev, apdev, release):
6334 check_eap_capa(dev[0], "MSCHAPV2")
6335 eap_test(dev[0], apdev[0], "21[3:26][6:7][99:99]", "TTLS", "user",
6336 release=release)
6337 rel = dev[0].get_status_field('hs20')
6338 if rel != str(release):
6339 raise Exception("Unexpected release number indicated: " + rel)
6340
6341 def test_ap_hs20_missing_pmf(dev, apdev):
6342 """Hotspot 2.0 connection attempt without PMF"""
6343 check_eap_capa(dev[0], "MSCHAPV2")
6344 bssid = apdev[0]['bssid']
6345 params = hs20_ap_params()
6346 params['hessid'] = bssid
6347 params['disable_dgaf'] = '1'
6348 hostapd.add_ap(apdev[0], params)
6349
6350 dev[0].hs20_enable()
6351 dev[0].connect("test-hs20", proto="RSN", key_mgmt="WPA-EAP", eap="TTLS",
6352 ieee80211w="0",
6353 identity="hs20-test", password="password",
6354 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
6355 scan_freq="2412", update_identifier="54321",
6356 roaming_consortium_selection="1020304050",
6357 wait_connect=False)
6358 ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT"], timeout=10)
6359 dev[0].request("DISCONNECT")
6360 if ev is None:
6361 raise Exception("Association rejection not reported")
6362 if "status_code=31" not in ev:
6363 raise Exception("Unexpected rejection reason: " + ev)