test_ap_config.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. # hostapd configuration tests
  2. # Copyright (c) 2014-2016, 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. import os
  7. import signal
  8. import time
  9. import logging
  10. logger = logging.getLogger(__name__)
  11. from remotehost import remote_compatible
  12. import hostapd
  13. from utils import alloc_fail, fail_test
  14. @remote_compatible
  15. def test_ap_config_errors(dev, apdev):
  16. """Various hostapd configuration errors"""
  17. # IEEE 802.11d without country code
  18. params = { "ssid": "foo", "ieee80211d": "1" }
  19. hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
  20. if "FAIL" not in hapd.request("ENABLE"):
  21. raise Exception("Unexpected ENABLE success (ieee80211d without country_code)")
  22. hostapd.remove_bss(apdev[0])
  23. # IEEE 802.11h without IEEE 802.11d
  24. params = { "ssid": "foo", "ieee80211h": "1" }
  25. hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
  26. if "FAIL" not in hapd.request("ENABLE"):
  27. raise Exception("Unexpected ENABLE success (ieee80211h without ieee80211d")
  28. hostapd.remove_bss(apdev[0])
  29. # Power Constraint without IEEE 802.11d
  30. params = { "ssid": "foo", "local_pwr_constraint": "1" }
  31. hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
  32. if "FAIL" not in hapd.request("ENABLE"):
  33. raise Exception("Unexpected ENABLE success (local_pwr_constraint without ieee80211d)")
  34. hostapd.remove_bss(apdev[0])
  35. # Spectrum management without Power Constraint
  36. params = { "ssid": "foo", "spectrum_mgmt_required": "1" }
  37. hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
  38. if "FAIL" not in hapd.request("ENABLE"):
  39. raise Exception("Unexpected ENABLE success (spectrum_mgmt_required without local_pwr_constraint)")
  40. hostapd.remove_bss(apdev[0])
  41. # IEEE 802.1X without authentication server
  42. params = { "ssid": "foo", "ieee8021x": "1" }
  43. hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
  44. if "FAIL" not in hapd.request("ENABLE"):
  45. raise Exception("Unexpected ENABLE success (ieee8021x)")
  46. hostapd.remove_bss(apdev[0])
  47. # RADIUS-PSK without macaddr_acl=2
  48. params = hostapd.wpa2_params(ssid="foo", passphrase="12345678")
  49. params["wpa_psk_radius"] = "1"
  50. hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
  51. if "FAIL" not in hapd.request("ENABLE"):
  52. raise Exception("Unexpected ENABLE success (wpa_psk_radius)")
  53. hostapd.remove_bss(apdev[0])
  54. # FT without NAS-Identifier
  55. params = { "wpa": "2",
  56. "wpa_key_mgmt": "FT-PSK",
  57. "rsn_pairwise": "CCMP",
  58. "wpa_passphrase": "12345678" }
  59. hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
  60. if "FAIL" not in hapd.request("ENABLE"):
  61. raise Exception("Unexpected ENABLE success (FT without nas_identifier)")
  62. hostapd.remove_bss(apdev[0])
  63. # Hotspot 2.0 without WPA2/CCMP
  64. params = hostapd.wpa2_params(ssid="foo")
  65. params['wpa_key_mgmt'] = "WPA-EAP"
  66. params['ieee8021x'] = "1"
  67. params['auth_server_addr'] = "127.0.0.1"
  68. params['auth_server_port'] = "1812"
  69. params['auth_server_shared_secret'] = "radius"
  70. params['interworking'] = "1"
  71. params['hs20'] = "1"
  72. params['wpa'] = "1"
  73. hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
  74. if "FAIL" not in hapd.request("ENABLE"):
  75. raise Exception("Unexpected ENABLE success (HS 2.0 without WPA2/CCMP)")
  76. hostapd.remove_bss(apdev[0])
  77. def test_ap_config_reload(dev, apdev, params):
  78. """hostapd configuration reload"""
  79. hapd = hostapd.add_ap(apdev[0], { "ssid": "foo" })
  80. hapd.set("ssid", "foobar")
  81. with open(os.path.join(params['logdir'], 'hostapd-test.pid'), "r") as f:
  82. pid = int(f.read())
  83. os.kill(pid, signal.SIGHUP)
  84. time.sleep(0.1)
  85. dev[0].connect("foobar", key_mgmt="NONE", scan_freq="2412")
  86. hapd.set("ssid", "foo")
  87. os.kill(pid, signal.SIGHUP)
  88. dev[0].wait_disconnected()
  89. dev[0].request("DISCONNECT")
  90. def test_ap_config_reload_file(dev, apdev, params):
  91. """hostapd configuration reload from file"""
  92. hapd = hostapd.add_iface(apdev[0], "bss-1.conf")
  93. hapd.enable()
  94. hapd.set("ssid", "foobar")
  95. with open(os.path.join(params['logdir'], 'hostapd-test.pid'), "r") as f:
  96. pid = int(f.read())
  97. os.kill(pid, signal.SIGHUP)
  98. time.sleep(0.1)
  99. dev[0].connect("foobar", key_mgmt="NONE", scan_freq="2412")
  100. hapd.set("ssid", "foo")
  101. os.kill(pid, signal.SIGHUP)
  102. dev[0].wait_disconnected()
  103. dev[0].request("DISCONNECT")
  104. def test_ap_config_reload_before_enable(dev, apdev, params):
  105. """hostapd configuration reload before enable"""
  106. hapd = hostapd.add_iface(apdev[0], "bss-1.conf")
  107. with open(os.path.join(params['logdir'], 'hostapd-test.pid'), "r") as f:
  108. pid = int(f.read())
  109. os.kill(pid, signal.SIGHUP)
  110. hapd.ping()
  111. def test_ap_config_sigusr1(dev, apdev, params):
  112. """hostapd SIGUSR1"""
  113. hapd = hostapd.add_ap(apdev[0], { "ssid": "foobar" })
  114. with open(os.path.join(params['logdir'], 'hostapd-test.pid'), "r") as f:
  115. pid = int(f.read())
  116. os.kill(pid, signal.SIGUSR1)
  117. dev[0].connect("foobar", key_mgmt="NONE", scan_freq="2412")
  118. os.kill(pid, signal.SIGUSR1)
  119. def test_ap_config_invalid_value(dev, apdev, params):
  120. """Ignoring invalid hostapd configuration parameter updates"""
  121. hapd = hostapd.add_ap(apdev[0], { "ssid": "test" }, no_enable=True)
  122. not_exist = "/tmp/hostapd-test/does-not-exist"
  123. tests = [ ("driver", "foobar"),
  124. ("ssid2", "Q"),
  125. ("macaddr_acl", "255"),
  126. ("accept_mac_file", not_exist),
  127. ("deny_mac_file", not_exist),
  128. ("eapol_version", "255"),
  129. ("eap_user_file", not_exist),
  130. ("wep_key_len_broadcast", "-1"),
  131. ("wep_key_len_unicast", "-1"),
  132. ("wep_rekey_period", "-1"),
  133. ("eap_rekey_period", "-1"),
  134. ("radius_client_addr", "foo"),
  135. ("acs_chan_bias", "-1:0.8"),
  136. ("acs_chan_bias", "1"),
  137. ("acs_chan_bias", "1:p"),
  138. ("acs_chan_bias", "1:-0.8"),
  139. ("acs_chan_bias", "1:0.8p"),
  140. ("dtim_period", "0"),
  141. ("bss_load_update_period", "-1"),
  142. ("send_probe_response", "255"),
  143. ("beacon_rate", "ht:-1"),
  144. ("beacon_rate", "ht:32"),
  145. ("beacon_rate", "vht:-1"),
  146. ("beacon_rate", "vht:10"),
  147. ("beacon_rate", "9"),
  148. ("beacon_rate", "10001"),
  149. ("vlan_file", not_exist),
  150. ("bss", ""),
  151. ("bssid", "foo"),
  152. ("extra_cred", not_exist),
  153. ("anqp_elem", "265"),
  154. ("anqp_elem", "265"),
  155. ("anqp_elem", "265:1"),
  156. ("anqp_elem", "265:1q"),
  157. ("fst_priority", ""),
  158. ("fils_cache_id", "q"),
  159. ("unknown-item", "foo") ]
  160. for field, val in tests:
  161. if "FAIL" not in hapd.request("SET %s %s" % (field, val)):
  162. raise Exception("Invalid %s accepted" % field)
  163. hapd.enable()
  164. dev[0].connect("test", key_mgmt="NONE", scan_freq="2412")
  165. def test_ap_config_eap_user_file_parsing(dev, apdev, params):
  166. """hostapd eap_user_file parsing"""
  167. tmp = os.path.join(params['logdir'], 'ap_vlan_file_parsing.tmp')
  168. hapd = hostapd.add_ap(apdev[0], { "ssid": "foobar" })
  169. for i in range(2):
  170. if "OK" not in hapd.request("SET eap_user_file auth_serv/eap_user.conf"):
  171. raise Exception("eap_user_file rejected")
  172. tests = [ "#\n\n*\tTLS\nradius_accept_attr=:",
  173. "foo\n",
  174. "\"foo\n",
  175. "\"foo\"\n",
  176. "\"foo\" FOOBAR\n",
  177. "\"foo\" " + 10*"TLS," + "TLS \"\n",
  178. "\"foo\" TLS \nfoo\n",
  179. "\"foo\" PEAP hash:foo\n",
  180. "\"foo\" PEAP hash:8846f7eaee8fb117ad06bdd830b7586q\n",
  181. "\"foo\" PEAP 01020\n",
  182. "\"foo\" PEAP 010q\n",
  183. "\"foo\" TLS\nradius_accept_attr=123:x:012\n",
  184. "\"foo\" TLS\nradius_accept_attr=123:x:012q\n",
  185. "\"foo\" TLS\nradius_accept_attr=123:Q:01\n",
  186. "\"foo\" TLS\nradius_accept_attr=123\nfoo\n" ]
  187. for t in tests:
  188. with open(tmp, "w") as f:
  189. f.write(t)
  190. if "FAIL" not in hapd.request("SET eap_user_file " + tmp):
  191. raise Exception("Invalid eap_user_file accepted")
  192. tests = [ ("\"foo\" TLS\n", 2, "hostapd_config_read_eap_user"),
  193. ("\"foo\" PEAP \"foo\"\n", 3, "hostapd_config_read_eap_user"),
  194. ("\"foo\" PEAP hash:8846f7eaee8fb117ad06bdd830b75861\n", 3,
  195. "hostapd_config_read_eap_user"),
  196. ("\"foo\" PEAP 0102\n", 3, "hostapd_config_read_eap_user"),
  197. ("\"foo\" TLS\nradius_accept_attr=123\n", 1,
  198. "=hostapd_parse_radius_attr"),
  199. ("\"foo\" TLS\nradius_accept_attr=123\n", 1,
  200. "wpabuf_alloc;hostapd_parse_radius_attr"),
  201. ("\"foo\" TLS\nradius_accept_attr=123:s:foo\n", 2,
  202. "hostapd_parse_radius_attr"),
  203. ("\"foo\" TLS\nradius_accept_attr=123:x:0102\n", 2,
  204. "hostapd_parse_radius_attr"),
  205. ("\"foo\" TLS\nradius_accept_attr=123:d:1\n", 2,
  206. "hostapd_parse_radius_attr"),
  207. ("* TLS\n", 1, "hostapd_config_read_eap_user") ]
  208. for t, count, func in tests:
  209. with alloc_fail(hapd, count, func):
  210. with open(tmp, "w") as f:
  211. f.write(t)
  212. if "FAIL" not in hapd.request("SET eap_user_file " + tmp):
  213. raise Exception("eap_user_file accepted during OOM")
  214. def test_ap_config_set_oom(dev, apdev):
  215. """hostapd configuration parsing OOM"""
  216. hapd = hostapd.add_ap(apdev[0], { "ssid": "foobar" })
  217. tests = [ (1, "hostapd_parse_das_client",
  218. "SET radius_das_client 192.168.1.123 pw"),
  219. (1, "hostapd_config_read_wep", "SET wep_key0 \"hello\""),
  220. (1, "hostapd_config_read_wep", "SET wep_key0 0102030405"),
  221. (1, "hostapd_parse_chanlist", "SET chanlist 1 6 11-13"),
  222. (1, "hostapd_config_bss", "SET bss foo"),
  223. (2, "hostapd_config_bss", "SET bss foo"),
  224. (3, "hostapd_config_bss", "SET bss foo"),
  225. (1, "add_r0kh",
  226. "SET r0kh 02:01:02:03:04:05 r0kh-1.example.com 000102030405060708090a0b0c0d0e0f"),
  227. (1, "add_r1kh",
  228. "SET r1kh 02:01:02:03:04:05 02:11:22:33:44:55 000102030405060708090a0b0c0d0e0f"),
  229. (1, "parse_roaming_consortium", "SET roaming_consortium 021122"),
  230. (1, "parse_lang_string", "SET venue_name eng:Example venue"),
  231. (1, "parse_3gpp_cell_net",
  232. "SET anqp_3gpp_cell_net 244,91;310,026;234,56"),
  233. (1, "parse_nai_realm", "SET nai_realm 0,example.com;example.net"),
  234. (2, "parse_nai_realm", "SET nai_realm 0,example.com;example.net"),
  235. (1, "parse_anqp_elem", "SET anqp_elem 265:0000"),
  236. (2, "parse_anqp_elem", "SET anqp_elem 266:000000"),
  237. (1, "hs20_parse_conn_capab", "SET hs20_conn_capab 1:0:2"),
  238. (1, "hs20_parse_wan_metrics",
  239. "SET hs20_wan_metrics 01:8000:1000:80:240:3000"),
  240. (1, "hs20_parse_icon",
  241. "SET hs20_icon 32:32:eng:image/png:icon32:/tmp/icon32.png"),
  242. (1, "hs20_parse_osu_server_uri",
  243. "SET osu_server_uri https://example.com/osu/"),
  244. (1, "hostapd_config_parse_acs_chan_bias",
  245. "SET acs_chan_bias 1:0.8 6:0.8 11:0.8"),
  246. (2, "hostapd_config_parse_acs_chan_bias",
  247. "SET acs_chan_bias 1:0.8 6:0.8 11:0.8"),
  248. (1, "parse_wpabuf_hex", "SET vendor_elements 01020304"),
  249. (1, "parse_fils_realm", "SET fils_realm example.com"),
  250. (1, "hostapd_config_fill",
  251. "SET pac_opaque_encr_key 000102030405060708090a0b0c0d0e0f"),
  252. (1, "hostapd_config_fill", "SET eap_message hello"),
  253. (1, "hostapd_config_fill",
  254. "SET wpa_psk 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"),
  255. (1, "hostapd_config_fill", "SET time_zone EST5"),
  256. (1, "hostapd_config_fill",
  257. "SET network_auth_type 02http://www.example.com/redirect/"),
  258. (1, "hostapd_config_fill", "SET domain_name example.com"),
  259. (1, "hostapd_config_fill", "SET hs20_operating_class 5173"),
  260. (1, "hostapd_config_fill", "SET own_ie_override 11223344"),
  261. (1, "hostapd_parse_intlist", "SET sae_groups 19 25"),
  262. (1, "hostapd_parse_intlist", "SET basic_rates 10 20 55 110"),
  263. (1, "hostapd_parse_intlist", "SET supported_rates 10 20 55 110") ]
  264. for count, func, cmd in tests:
  265. with alloc_fail(hapd, count, func):
  266. if "FAIL" not in hapd.request(cmd):
  267. raise Exception("Command accepted during OOM: " + cmd)
  268. hapd.set("hs20_icon", "32:32:eng:image/png:icon32:/tmp/icon32.png")
  269. hapd.set("hs20_conn_capab", "1:0:2")
  270. hapd.set("nai_realm", "0,example.com;example.net")
  271. hapd.set("venue_name", "eng:Example venue")
  272. hapd.set("roaming_consortium", "021122")
  273. hapd.set("osu_server_uri", "https://example.com/osu/")
  274. hapd.set("vendor_elements", "01020304")
  275. hapd.set("vendor_elements", "01020304")
  276. hapd.set("vendor_elements", "")
  277. hapd.set("lci", "11223344")
  278. hapd.set("civic", "11223344")
  279. hapd.set("lci", "")
  280. hapd.set("civic", "")
  281. tests = [ (1, "hs20_parse_icon",
  282. "SET hs20_icon 32:32:eng:image/png:icon32:/tmp/icon32.png"),
  283. (1, "parse_roaming_consortium", "SET roaming_consortium 021122"),
  284. (2, "parse_nai_realm", "SET nai_realm 0,example.com;example.net"),
  285. (1, "parse_lang_string", "SET venue_name eng:Example venue"),
  286. (1, "hs20_parse_osu_server_uri",
  287. "SET osu_server_uri https://example.com/osu/"),
  288. (1, "hs20_parse_osu_nai", "SET osu_nai anonymous@example.com"),
  289. (1, "hostapd_parse_intlist", "SET osu_method_list 1 0"),
  290. (1, "hs20_parse_osu_icon", "SET osu_icon icon32"),
  291. (2, "hs20_parse_osu_icon", "SET osu_icon icon32"),
  292. (2, "hs20_parse_osu_icon", "SET osu_icon icon32"),
  293. (1, "hs20_parse_conn_capab", "SET hs20_conn_capab 1:0:2") ]
  294. for count, func, cmd in tests:
  295. with alloc_fail(hapd, count, func):
  296. if "FAIL" not in hapd.request(cmd):
  297. raise Exception("Command accepted during OOM (2): " + cmd)
  298. tests = [ (1, "parse_fils_realm", "SET fils_realm example.com") ]
  299. for count, func, cmd in tests:
  300. with fail_test(hapd, count, func):
  301. if "FAIL" not in hapd.request(cmd):
  302. raise Exception("Command accepted during FAIL_TEST: " + cmd)
  303. def test_ap_config_set_errors(dev, apdev):
  304. """hostapd configuration parsing errors"""
  305. hapd = hostapd.add_ap(apdev[0], { "ssid": "foobar" })
  306. hapd.set("wep_key0", '"hello"')
  307. hapd.set("wep_key1", '"hello"')
  308. hapd.set("wep_key0", '')
  309. hapd.set("wep_key0", '"hello"')
  310. if "FAIL" not in hapd.request("SET wep_key1 \"hello\""):
  311. raise Exception("SET wep_key1 allowed to override existing key")
  312. hapd.set("wep_key1", '')
  313. hapd.set("wep_key1", '"hello"')
  314. hapd.set("auth_server_addr", "127.0.0.1")
  315. hapd.set("acct_server_addr", "127.0.0.1")
  316. tests = [ "SET eap_reauth_period -1",
  317. "SET fst_llt ",
  318. "SET auth_server_addr_replace foo",
  319. "SET acct_server_addr_replace foo" ]
  320. for t in tests:
  321. if "FAIL" not in hapd.request(t):
  322. raise Exception("Invalid command accepted: " + t)
  323. # Deprecated entries
  324. hapd.set("tx_queue_after_beacon_aifs", '2')
  325. hapd.set("tx_queue_beacon_aifs", '2')
  326. hapd.set("tx_queue_data9_aifs", '2')
  327. hapd.set("debug", '1')
  328. hapd.set("dump_file", '/tmp/hostapd-test-dump')
  329. hapd.set("eap_authenticator", '0')
  330. hapd.set("radio_measurements", '0')
  331. hapd.set("radio_measurements", '1')
  332. # Various extra coverage (not really errors)
  333. hapd.set("logger_syslog_level", '1')
  334. hapd.set("logger_syslog", '0')
  335. for i in range(50000):
  336. if "OK" not in hapd.request("SET hs20_conn_capab 17:5060:0"):
  337. logger.info("hs20_conn_capab limit at %d" % i)
  338. break
  339. if i < 1000 or i >= 49999:
  340. raise Exception("hs20_conn_capab limit not seen")