2 # Copyright (c) 2013-2016, Jouni Malinen <j@w1.fi>
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
7 from remotehost import remote_compatible
12 logger = logging.getLogger()
21 from utils import HwsimSkip, require_under_vm, skip_with_fips, fail_test
22 from test_ap_hs20 import build_dhcp_ack
23 from test_ap_ft import ft_params1
25 def connect(dev, ssid, wait_connect=True):
26 dev.connect(ssid, key_mgmt="WPA-EAP", scan_freq="2412",
27 eap="PSK", identity="psk.user@example.com",
28 password_hex="0123456789abcdef0123456789abcdef",
29 wait_connect=wait_connect)
32 def test_radius_auth_unreachable(dev, apdev):
33 """RADIUS Authentication server unreachable"""
34 params = hostapd.wpa2_eap_params(ssid="radius-auth")
35 params['auth_server_port'] = "18139"
36 hapd = hostapd.add_ap(apdev[0], params)
37 connect(dev[0], "radius-auth", wait_connect=False)
38 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"])
40 raise Exception("Timeout on EAP start")
41 logger.info("Checking for RADIUS retries")
44 if "radiusAuthClientAccessRequests" not in mib:
45 raise Exception("Missing MIB fields")
46 if int(mib["radiusAuthClientAccessRetransmissions"]) < 1:
47 raise Exception("Missing RADIUS Authentication retransmission")
48 if int(mib["radiusAuthClientPendingRequests"]) < 1:
49 raise Exception("Missing pending RADIUS Authentication request")
51 def test_radius_auth_unreachable2(dev, apdev):
52 """RADIUS Authentication server unreachable (2)"""
53 subprocess.call(['ip', 'ro', 'replace', '192.168.213.17', 'dev', 'lo'])
54 params = hostapd.wpa2_eap_params(ssid="radius-auth")
55 params['auth_server_addr'] = "192.168.213.17"
56 params['auth_server_port'] = "18139"
57 hapd = hostapd.add_ap(apdev[0], params)
58 subprocess.call(['ip', 'ro', 'del', '192.168.213.17', 'dev', 'lo'])
59 connect(dev[0], "radius-auth", wait_connect=False)
60 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"])
62 raise Exception("Timeout on EAP start")
63 logger.info("Checking for RADIUS retries")
66 if "radiusAuthClientAccessRequests" not in mib:
67 raise Exception("Missing MIB fields")
68 if int(mib["radiusAuthClientAccessRetransmissions"]) < 1:
69 raise Exception("Missing RADIUS Authentication retransmission")
71 def test_radius_auth_unreachable3(dev, apdev):
72 """RADIUS Authentication server initially unreachable, but then available"""
73 subprocess.call(['ip', 'ro', 'replace', 'blackhole', '192.168.213.18'])
74 params = hostapd.wpa2_eap_params(ssid="radius-auth")
75 params['auth_server_addr'] = "192.168.213.18"
76 hapd = hostapd.add_ap(apdev[0], params)
77 connect(dev[0], "radius-auth", wait_connect=False)
78 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"])
80 raise Exception("Timeout on EAP start")
81 subprocess.call(['ip', 'ro', 'del', 'blackhole', '192.168.213.18'])
83 dev[0].request("DISCONNECT")
84 hapd.set('auth_server_addr_replace', '127.0.0.1')
85 dev[0].request("RECONNECT")
87 dev[0].wait_connected()
89 def test_radius_acct_unreachable(dev, apdev):
90 """RADIUS Accounting server unreachable"""
91 params = hostapd.wpa2_eap_params(ssid="radius-acct")
92 params['acct_server_addr'] = "127.0.0.1"
93 params['acct_server_port'] = "18139"
94 params['acct_server_shared_secret'] = "radius"
95 hapd = hostapd.add_ap(apdev[0], params)
96 connect(dev[0], "radius-acct")
97 logger.info("Checking for RADIUS retries")
100 if "radiusAccClientRetransmissions" not in mib:
101 raise Exception("Missing MIB fields")
102 if int(mib["radiusAccClientRetransmissions"]) < 2:
103 raise Exception("Missing RADIUS Accounting retransmissions")
104 if int(mib["radiusAccClientPendingRequests"]) < 2:
105 raise Exception("Missing pending RADIUS Accounting requests")
107 def test_radius_acct_unreachable2(dev, apdev):
108 """RADIUS Accounting server unreachable(2)"""
109 subprocess.call(['ip', 'ro', 'replace', '192.168.213.17', 'dev', 'lo'])
110 params = hostapd.wpa2_eap_params(ssid="radius-acct")
111 params['acct_server_addr'] = "192.168.213.17"
112 params['acct_server_port'] = "18139"
113 params['acct_server_shared_secret'] = "radius"
114 hapd = hostapd.add_ap(apdev[0], params)
115 subprocess.call(['ip', 'ro', 'del', '192.168.213.17', 'dev', 'lo'])
116 connect(dev[0], "radius-acct")
117 logger.info("Checking for RADIUS retries")
120 if "radiusAccClientRetransmissions" not in mib:
121 raise Exception("Missing MIB fields")
122 if int(mib["radiusAccClientRetransmissions"]) < 1 and int(mib["radiusAccClientPendingRequests"]) < 1:
123 raise Exception("Missing pending or retransmitted RADIUS Accounting requests")
125 def test_radius_acct_unreachable3(dev, apdev):
126 """RADIUS Accounting server initially unreachable, but then available"""
128 subprocess.call(['ip', 'ro', 'replace', 'blackhole', '192.168.213.18'])
129 as_hapd = hostapd.Hostapd("as")
130 as_mib_start = as_hapd.get_mib(param="radius_server")
131 params = hostapd.wpa2_eap_params(ssid="radius-acct")
132 params['acct_server_addr'] = "192.168.213.18"
133 params['acct_server_port'] = "1813"
134 params['acct_server_shared_secret'] = "radius"
135 hapd = hostapd.add_ap(apdev[0], params)
136 connect(dev[0], "radius-acct")
137 subprocess.call(['ip', 'ro', 'del', 'blackhole', '192.168.213.18'])
139 dev[0].request("DISCONNECT")
140 hapd.set('acct_server_addr_replace', '127.0.0.1')
141 dev[0].request("RECONNECT")
142 dev[0].wait_connected()
144 as_mib_end = as_hapd.get_mib(param="radius_server")
145 req_s = int(as_mib_start['radiusAccServTotalResponses'])
146 req_e = int(as_mib_end['radiusAccServTotalResponses'])
148 raise Exception("Unexpected RADIUS server acct MIB value")
150 def test_radius_acct_unreachable4(dev, apdev):
151 """RADIUS Accounting server unreachable and multiple STAs"""
152 params = hostapd.wpa2_eap_params(ssid="radius-acct")
153 params['acct_server_addr'] = "127.0.0.1"
154 params['acct_server_port'] = "18139"
155 params['acct_server_shared_secret'] = "radius"
156 hapd = hostapd.add_ap(apdev[0], params)
158 connect(dev[0], "radius-acct")
159 dev[0].request("REMOVE_NETWORK all")
160 dev[0].wait_disconnected()
162 def test_radius_acct(dev, apdev):
163 """RADIUS Accounting"""
164 as_hapd = hostapd.Hostapd("as")
165 as_mib_start = as_hapd.get_mib(param="radius_server")
166 params = hostapd.wpa2_eap_params(ssid="radius-acct")
167 params['acct_server_addr'] = "127.0.0.1"
168 params['acct_server_port'] = "1813"
169 params['acct_server_shared_secret'] = "radius"
170 params['radius_auth_req_attr'] = [ "126:s:Operator", "77:s:testing" ]
171 params['radius_acct_req_attr'] = [ "126:s:Operator", "77:s:testing" ]
172 hapd = hostapd.add_ap(apdev[0], params)
173 connect(dev[0], "radius-acct")
174 dev[1].connect("radius-acct", key_mgmt="WPA-EAP", scan_freq="2412",
175 eap="PAX", identity="test-class",
176 password_hex="0123456789abcdef0123456789abcdef")
177 dev[2].connect("radius-acct", key_mgmt="WPA-EAP",
178 eap="GPSK", identity="gpsk-cui",
179 password="abcdefghijklmnop0123456789abcdef",
181 logger.info("Checking for RADIUS counters")
185 if int(mib['radiusAccClientResponses']) >= 3:
190 raise Exception("Did not receive Accounting-Response packets")
192 if int(mib['radiusAccClientRetransmissions']) > 0:
193 raise Exception("Unexpected Accounting-Request retransmission")
195 as_mib_end = as_hapd.get_mib(param="radius_server")
197 req_s = int(as_mib_start['radiusAccServTotalRequests'])
198 req_e = int(as_mib_end['radiusAccServTotalRequests'])
199 if req_e < req_s + 2:
200 raise Exception("Unexpected RADIUS server acct MIB value")
202 acc_s = int(as_mib_start['radiusAuthServAccessAccepts'])
203 acc_e = int(as_mib_end['radiusAuthServAccessAccepts'])
204 if acc_e < acc_s + 1:
205 raise Exception("Unexpected RADIUS server auth MIB value")
207 def test_radius_acct_non_ascii_ssid(dev, apdev):
208 """RADIUS Accounting and non-ASCII SSID"""
209 params = hostapd.wpa2_eap_params()
210 params['acct_server_addr'] = "127.0.0.1"
211 params['acct_server_port'] = "1813"
212 params['acct_server_shared_secret'] = "radius"
213 ssid2 = "740665007374"
214 params['ssid2'] = ssid2
215 hostapd.add_ap(apdev[0], params)
216 dev[0].connect(ssid2=ssid2, key_mgmt="WPA-EAP", scan_freq="2412",
217 eap="PSK", identity="psk.user@example.com",
218 password_hex="0123456789abcdef0123456789abcdef")
220 def test_radius_acct_pmksa_caching(dev, apdev):
221 """RADIUS Accounting with PMKSA caching"""
222 as_hapd = hostapd.Hostapd("as")
223 as_mib_start = as_hapd.get_mib(param="radius_server")
224 params = hostapd.wpa2_eap_params(ssid="radius-acct")
225 params['acct_server_addr'] = "127.0.0.1"
226 params['acct_server_port'] = "1813"
227 params['acct_server_shared_secret'] = "radius"
228 hapd = hostapd.add_ap(apdev[0], params)
229 connect(dev[0], "radius-acct")
230 dev[1].connect("radius-acct", key_mgmt="WPA-EAP", scan_freq="2412",
231 eap="PAX", identity="test-class",
232 password_hex="0123456789abcdef0123456789abcdef")
233 for d in [ dev[0], dev[1] ]:
234 d.request("REASSOCIATE")
235 d.wait_connected(timeout=15, error="Reassociation timed out")
240 if int(mib['radiusAccClientResponses']) >= 4:
245 raise Exception("Did not receive Accounting-Response packets")
247 if int(mib['radiusAccClientRetransmissions']) > 0:
248 raise Exception("Unexpected Accounting-Request retransmission")
250 as_mib_end = as_hapd.get_mib(param="radius_server")
252 req_s = int(as_mib_start['radiusAccServTotalRequests'])
253 req_e = int(as_mib_end['radiusAccServTotalRequests'])
254 if req_e < req_s + 2:
255 raise Exception("Unexpected RADIUS server acct MIB value")
257 acc_s = int(as_mib_start['radiusAuthServAccessAccepts'])
258 acc_e = int(as_mib_end['radiusAuthServAccessAccepts'])
259 if acc_e < acc_s + 1:
260 raise Exception("Unexpected RADIUS server auth MIB value")
262 def test_radius_acct_interim(dev, apdev):
263 """RADIUS Accounting interim update"""
264 as_hapd = hostapd.Hostapd("as")
265 params = hostapd.wpa2_eap_params(ssid="radius-acct")
266 params['acct_server_addr'] = "127.0.0.1"
267 params['acct_server_port'] = "1813"
268 params['acct_server_shared_secret'] = "radius"
269 params['radius_acct_interim_interval'] = "1"
270 hapd = hostapd.add_ap(apdev[0], params)
271 connect(dev[0], "radius-acct")
272 logger.info("Checking for RADIUS counters")
273 as_mib_start = as_hapd.get_mib(param="radius_server")
275 as_mib_end = as_hapd.get_mib(param="radius_server")
276 req_s = int(as_mib_start['radiusAccServTotalRequests'])
277 req_e = int(as_mib_end['radiusAccServTotalRequests'])
278 if req_e < req_s + 3:
279 raise Exception("Unexpected RADIUS server acct MIB value")
281 def test_radius_acct_interim_unreachable(dev, apdev):
282 """RADIUS Accounting interim update with unreachable server"""
283 params = hostapd.wpa2_eap_params(ssid="radius-acct")
284 params['acct_server_addr'] = "127.0.0.1"
285 params['acct_server_port'] = "18139"
286 params['acct_server_shared_secret'] = "radius"
287 params['radius_acct_interim_interval'] = "1"
288 hapd = hostapd.add_ap(apdev[0], params)
289 start = hapd.get_mib()
290 connect(dev[0], "radius-acct")
291 logger.info("Waiting for interium accounting updates")
294 req_s = int(start['radiusAccClientTimeouts'])
295 req_e = int(end['radiusAccClientTimeouts'])
296 if req_e < req_s + 2:
297 raise Exception("Unexpected RADIUS server acct MIB value")
299 def test_radius_acct_interim_unreachable2(dev, apdev):
300 """RADIUS Accounting interim update with unreachable server (retry)"""
301 params = hostapd.wpa2_eap_params(ssid="radius-acct")
302 params['acct_server_addr'] = "127.0.0.1"
303 params['acct_server_port'] = "18139"
304 params['acct_server_shared_secret'] = "radius"
305 # Use long enough interim update interval to allow RADIUS retransmission
306 # case (3 seconds) to trigger first.
307 params['radius_acct_interim_interval'] = "4"
308 hapd = hostapd.add_ap(apdev[0], params)
309 start = hapd.get_mib()
310 connect(dev[0], "radius-acct")
311 logger.info("Waiting for interium accounting updates")
314 req_s = int(start['radiusAccClientTimeouts'])
315 req_e = int(end['radiusAccClientTimeouts'])
316 if req_e < req_s + 2:
317 raise Exception("Unexpected RADIUS server acct MIB value")
319 def test_radius_acct_ipaddr(dev, apdev):
320 """RADIUS Accounting and Framed-IP-Address"""
322 _test_radius_acct_ipaddr(dev, apdev)
324 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
325 stderr=open('/dev/null', 'w'))
326 subprocess.call(['brctl', 'delbr', 'ap-br0'],
327 stderr=open('/dev/null', 'w'))
329 def _test_radius_acct_ipaddr(dev, apdev):
330 params = { "ssid": "radius-acct-open",
331 'acct_server_addr': "127.0.0.1",
332 'acct_server_port': "1813",
333 'acct_server_shared_secret': "radius",
337 hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
341 # For now, do not report failures due to missing kernel support
342 raise HwsimSkip("Could not start hostapd - assume proxyarp not supported in kernel version")
343 bssid = apdev[0]['bssid']
345 subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
346 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
348 dev[0].connect("radius-acct-open", key_mgmt="NONE", scan_freq="2412")
349 addr0 = dev[0].own_addr()
351 pkt = build_dhcp_ack(dst_ll="ff:ff:ff:ff:ff:ff", src_ll=bssid,
352 ip_src="192.168.1.1", ip_dst="255.255.255.255",
353 yiaddr="192.168.1.123", chaddr=addr0)
354 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
355 raise Exception("DATA_TEST_FRAME failed")
357 dev[0].request("DISCONNECT")
358 dev[0].wait_disconnected()
361 def send_and_check_reply(srv, req, code, error_cause=0):
362 reply = srv.SendPacket(req)
363 logger.debug("RADIUS response from hostapd")
364 for i in reply.keys():
365 logger.debug("%s: %s" % (i, reply[i]))
366 if reply.code != code:
367 raise Exception("Unexpected response code")
369 if 'Error-Cause' not in reply:
370 raise Exception("Missing Error-Cause")
371 if reply['Error-Cause'][0] != error_cause:
372 raise Exception("Unexpected Error-Cause: {}".format(reply['Error-Cause']))
374 def test_radius_acct_psk(dev, apdev):
375 """RADIUS Accounting - PSK"""
376 as_hapd = hostapd.Hostapd("as")
377 params = hostapd.wpa2_params(ssid="radius-acct", passphrase="12345678")
378 params['acct_server_addr'] = "127.0.0.1"
379 params['acct_server_port'] = "1813"
380 params['acct_server_shared_secret'] = "radius"
381 hapd = hostapd.add_ap(apdev[0], params)
382 dev[0].connect("radius-acct", psk="12345678", scan_freq="2412")
384 def test_radius_acct_psk_sha256(dev, apdev):
385 """RADIUS Accounting - PSK SHA256"""
386 as_hapd = hostapd.Hostapd("as")
387 params = hostapd.wpa2_params(ssid="radius-acct", passphrase="12345678")
388 params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
389 params['acct_server_addr'] = "127.0.0.1"
390 params['acct_server_port'] = "1813"
391 params['acct_server_shared_secret'] = "radius"
392 hapd = hostapd.add_ap(apdev[0], params)
393 dev[0].connect("radius-acct", key_mgmt="WPA-PSK-SHA256",
394 psk="12345678", scan_freq="2412")
396 def test_radius_acct_ft_psk(dev, apdev):
397 """RADIUS Accounting - FT-PSK"""
398 as_hapd = hostapd.Hostapd("as")
399 params = ft_params1(ssid="radius-acct", passphrase="12345678")
400 params['acct_server_addr'] = "127.0.0.1"
401 params['acct_server_port'] = "1813"
402 params['acct_server_shared_secret'] = "radius"
403 hapd = hostapd.add_ap(apdev[0], params)
404 dev[0].connect("radius-acct", key_mgmt="FT-PSK",
405 psk="12345678", scan_freq="2412")
407 def test_radius_acct_ieee8021x(dev, apdev):
408 """RADIUS Accounting - IEEE 802.1X"""
409 skip_with_fips(dev[0])
410 as_hapd = hostapd.Hostapd("as")
411 params = hostapd.radius_params()
412 params["ssid"] = "radius-acct-1x"
413 params["ieee8021x"] = "1"
414 params["wep_key_len_broadcast"] = "13"
415 params["wep_key_len_unicast"] = "13"
416 params['acct_server_addr'] = "127.0.0.1"
417 params['acct_server_port'] = "1813"
418 params['acct_server_shared_secret'] = "radius"
419 hapd = hostapd.add_ap(apdev[0], params)
420 dev[0].connect("radius-acct-1x", key_mgmt="IEEE8021X", eap="PSK",
421 identity="psk.user@example.com",
422 password_hex="0123456789abcdef0123456789abcdef",
425 def test_radius_das_disconnect(dev, apdev):
426 """RADIUS Dynamic Authorization Extensions - Disconnect"""
430 import pyrad.dictionary
433 raise HwsimSkip("No pyrad modules available")
435 params = hostapd.wpa2_eap_params(ssid="radius-das")
436 params['radius_das_port'] = "3799"
437 params['radius_das_client'] = "127.0.0.1 secret"
438 params['radius_das_require_event_timestamp'] = "1"
439 params['own_ip_addr'] = "127.0.0.1"
440 params['nas_identifier'] = "nas.example.com"
441 hapd = hostapd.add_ap(apdev[0], params)
442 connect(dev[0], "radius-das")
443 addr = dev[0].p2p_interface_addr()
444 sta = hapd.get_sta(addr)
445 id = sta['dot1xAuthSessionId']
447 dict = pyrad.dictionary.Dictionary("dictionary.radius")
449 srv = pyrad.client.Client(server="127.0.0.1", acctport=3799,
450 secret="secret", dict=dict)
454 logger.info("Disconnect-Request with incorrect secret")
455 req = radius_das.DisconnectPacket(dict=dict, secret="incorrect",
457 NAS_Identifier="localhost",
458 Event_Timestamp=int(time.time()))
461 reply = srv.SendPacket(req)
462 raise Exception("Unexpected response to Disconnect-Request")
463 except pyrad.client.Timeout:
464 logger.info("Disconnect-Request with incorrect secret properly ignored")
466 logger.info("Disconnect-Request without Event-Timestamp")
467 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
468 User_Name="psk.user@example.com")
471 reply = srv.SendPacket(req)
472 raise Exception("Unexpected response to Disconnect-Request")
473 except pyrad.client.Timeout:
474 logger.info("Disconnect-Request without Event-Timestamp properly ignored")
476 logger.info("Disconnect-Request with non-matching Event-Timestamp")
477 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
478 User_Name="psk.user@example.com",
479 Event_Timestamp=123456789)
482 reply = srv.SendPacket(req)
483 raise Exception("Unexpected response to Disconnect-Request")
484 except pyrad.client.Timeout:
485 logger.info("Disconnect-Request with non-matching Event-Timestamp properly ignored")
487 logger.info("Disconnect-Request with unsupported attribute")
488 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
491 Event_Timestamp=int(time.time()))
492 send_and_check_reply(srv, req, pyrad.packet.DisconnectNAK, 401)
494 logger.info("Disconnect-Request with invalid Calling-Station-Id")
495 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
497 Calling_Station_Id="foo",
498 Event_Timestamp=int(time.time()))
499 send_and_check_reply(srv, req, pyrad.packet.DisconnectNAK, 407)
501 logger.info("Disconnect-Request with mismatching User-Name")
502 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
504 Event_Timestamp=int(time.time()))
505 send_and_check_reply(srv, req, pyrad.packet.DisconnectNAK, 503)
507 logger.info("Disconnect-Request with mismatching Calling-Station-Id")
508 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
509 Calling_Station_Id="12:34:56:78:90:aa",
510 Event_Timestamp=int(time.time()))
511 send_and_check_reply(srv, req, pyrad.packet.DisconnectNAK, 503)
513 logger.info("Disconnect-Request with mismatching Acct-Session-Id")
514 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
515 Acct_Session_Id="12345678-87654321",
516 Event_Timestamp=int(time.time()))
517 send_and_check_reply(srv, req, pyrad.packet.DisconnectNAK, 503)
519 logger.info("Disconnect-Request with mismatching Acct-Session-Id (len)")
520 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
521 Acct_Session_Id="12345678",
522 Event_Timestamp=int(time.time()))
523 send_and_check_reply(srv, req, pyrad.packet.DisconnectNAK, 503)
525 logger.info("Disconnect-Request with mismatching Acct-Multi-Session-Id")
526 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
527 Acct_Multi_Session_Id="12345678+87654321",
528 Event_Timestamp=int(time.time()))
529 send_and_check_reply(srv, req, pyrad.packet.DisconnectNAK, 503)
531 logger.info("Disconnect-Request with mismatching Acct-Multi-Session-Id (len)")
532 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
533 Acct_Multi_Session_Id="12345678",
534 Event_Timestamp=int(time.time()))
535 send_and_check_reply(srv, req, pyrad.packet.DisconnectNAK, 503)
537 logger.info("Disconnect-Request with no session identification attributes")
538 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
539 Event_Timestamp=int(time.time()))
540 send_and_check_reply(srv, req, pyrad.packet.DisconnectNAK, 503)
542 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1)
544 raise Exception("Unexpected disconnection")
546 logger.info("Disconnect-Request with mismatching NAS-IP-Address")
547 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
548 NAS_IP_Address="192.168.3.4",
550 Event_Timestamp=int(time.time()))
551 send_and_check_reply(srv, req, pyrad.packet.DisconnectNAK, 403)
553 logger.info("Disconnect-Request with mismatching NAS-Identifier")
554 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
555 NAS_Identifier="unknown.example.com",
557 Event_Timestamp=int(time.time()))
558 send_and_check_reply(srv, req, pyrad.packet.DisconnectNAK, 403)
560 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1)
562 raise Exception("Unexpected disconnection")
564 logger.info("Disconnect-Request with matching Acct-Session-Id")
565 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
566 NAS_IP_Address="127.0.0.1",
567 NAS_Identifier="nas.example.com",
569 Event_Timestamp=int(time.time()))
570 send_and_check_reply(srv, req, pyrad.packet.DisconnectACK)
572 dev[0].wait_disconnected(timeout=10)
573 dev[0].wait_connected(timeout=10, error="Re-connection timed out")
575 logger.info("Disconnect-Request with matching Acct-Multi-Session-Id")
576 sta = hapd.get_sta(addr)
577 multi_sess_id = sta['authMultiSessionId']
578 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
579 NAS_IP_Address="127.0.0.1",
580 NAS_Identifier="nas.example.com",
581 Acct_Multi_Session_Id=multi_sess_id,
582 Event_Timestamp=int(time.time()))
583 send_and_check_reply(srv, req, pyrad.packet.DisconnectACK)
585 dev[0].wait_disconnected(timeout=10)
586 dev[0].wait_connected(timeout=10, error="Re-connection timed out")
588 logger.info("Disconnect-Request with matching User-Name")
589 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
590 NAS_Identifier="nas.example.com",
591 User_Name="psk.user@example.com",
592 Event_Timestamp=int(time.time()))
593 send_and_check_reply(srv, req, pyrad.packet.DisconnectACK)
595 dev[0].wait_disconnected(timeout=10)
596 dev[0].wait_connected(timeout=10, error="Re-connection timed out")
598 logger.info("Disconnect-Request with matching Calling-Station-Id")
599 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
600 NAS_IP_Address="127.0.0.1",
601 Calling_Station_Id=addr,
602 Event_Timestamp=int(time.time()))
603 send_and_check_reply(srv, req, pyrad.packet.DisconnectACK)
605 dev[0].wait_disconnected(timeout=10)
606 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED", "CTRL-EVENT-CONNECTED"])
608 raise Exception("Timeout while waiting for re-connection")
609 if "CTRL-EVENT-EAP-STARTED" not in ev:
610 raise Exception("Unexpected skipping of EAP authentication in reconnection")
611 dev[0].wait_connected(timeout=10, error="Re-connection timed out")
613 logger.info("Disconnect-Request with matching Calling-Station-Id and non-matching CUI")
614 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
615 Calling_Station_Id=addr,
616 Chargeable_User_Identity="foo@example.com",
617 Event_Timestamp=int(time.time()))
618 send_and_check_reply(srv, req, pyrad.packet.DisconnectNAK, error_cause=503)
620 logger.info("Disconnect-Request with matching CUI")
621 dev[1].connect("radius-das", key_mgmt="WPA-EAP",
622 eap="GPSK", identity="gpsk-cui",
623 password="abcdefghijklmnop0123456789abcdef",
625 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
626 Chargeable_User_Identity="gpsk-chargeable-user-identity",
627 Event_Timestamp=int(time.time()))
628 send_and_check_reply(srv, req, pyrad.packet.DisconnectACK)
630 dev[1].wait_disconnected(timeout=10)
631 dev[1].wait_connected(timeout=10, error="Re-connection timed out")
633 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1)
635 raise Exception("Unexpected disconnection")
637 connect(dev[2], "radius-das")
639 logger.info("Disconnect-Request with matching User-Name - multiple sessions matching")
640 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
641 NAS_Identifier="nas.example.com",
642 User_Name="psk.user@example.com",
643 Event_Timestamp=int(time.time()))
644 send_and_check_reply(srv, req, pyrad.packet.DisconnectNAK, error_cause=508)
646 logger.info("Disconnect-Request with User-Name matching multiple sessions, Calling-Station-Id only one")
647 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
648 NAS_Identifier="nas.example.com",
649 Calling_Station_Id=addr,
650 User_Name="psk.user@example.com",
651 Event_Timestamp=int(time.time()))
652 send_and_check_reply(srv, req, pyrad.packet.DisconnectACK)
654 dev[0].wait_disconnected(timeout=10)
655 dev[0].wait_connected(timeout=10, error="Re-connection timed out")
657 ev = dev[2].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1)
659 raise Exception("Unexpected disconnection")
661 logger.info("Disconnect-Request with matching Acct-Multi-Session-Id after disassociation")
662 sta = hapd.get_sta(addr)
663 multi_sess_id = sta['authMultiSessionId']
664 dev[0].request("DISCONNECT")
665 dev[0].wait_disconnected(timeout=10)
666 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
667 NAS_IP_Address="127.0.0.1",
668 NAS_Identifier="nas.example.com",
669 Acct_Multi_Session_Id=multi_sess_id,
670 Event_Timestamp=int(time.time()))
671 send_and_check_reply(srv, req, pyrad.packet.DisconnectACK)
673 dev[0].request("RECONNECT")
674 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=15)
676 raise Exception("Timeout on EAP start")
677 dev[0].wait_connected(timeout=15)
679 logger.info("Disconnect-Request with matching User-Name after disassociation")
680 dev[0].request("DISCONNECT")
681 dev[0].wait_disconnected(timeout=10)
682 dev[2].request("DISCONNECT")
683 dev[2].wait_disconnected(timeout=10)
684 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
685 NAS_IP_Address="127.0.0.1",
686 NAS_Identifier="nas.example.com",
687 User_Name="psk.user@example.com",
688 Event_Timestamp=int(time.time()))
689 send_and_check_reply(srv, req, pyrad.packet.DisconnectACK)
691 logger.info("Disconnect-Request with matching CUI after disassociation")
692 dev[1].request("DISCONNECT")
693 dev[1].wait_disconnected(timeout=10)
694 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
695 NAS_IP_Address="127.0.0.1",
696 NAS_Identifier="nas.example.com",
697 Chargeable_User_Identity="gpsk-chargeable-user-identity",
698 Event_Timestamp=int(time.time()))
699 send_and_check_reply(srv, req, pyrad.packet.DisconnectACK)
701 logger.info("Disconnect-Request with matching Calling-Station-Id after disassociation")
702 dev[0].request("RECONNECT")
703 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=15)
705 raise Exception("Timeout on EAP start")
706 dev[0].wait_connected(timeout=15)
707 dev[0].request("DISCONNECT")
708 dev[0].wait_disconnected(timeout=10)
709 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
710 NAS_IP_Address="127.0.0.1",
711 NAS_Identifier="nas.example.com",
712 Calling_Station_Id=addr,
713 Event_Timestamp=int(time.time()))
714 send_and_check_reply(srv, req, pyrad.packet.DisconnectACK)
716 logger.info("Disconnect-Request with mismatching Calling-Station-Id after disassociation")
717 req = radius_das.DisconnectPacket(dict=dict, secret="secret",
718 NAS_IP_Address="127.0.0.1",
719 NAS_Identifier="nas.example.com",
720 Calling_Station_Id=addr,
721 Event_Timestamp=int(time.time()))
722 send_and_check_reply(srv, req, pyrad.packet.DisconnectNAK, error_cause=503)
724 def test_radius_das_coa(dev, apdev):
725 """RADIUS Dynamic Authorization Extensions - CoA"""
729 import pyrad.dictionary
732 raise HwsimSkip("No pyrad modules available")
734 params = hostapd.wpa2_eap_params(ssid="radius-das")
735 params['radius_das_port'] = "3799"
736 params['radius_das_client'] = "127.0.0.1 secret"
737 params['radius_das_require_event_timestamp'] = "1"
738 hapd = hostapd.add_ap(apdev[0], params)
739 connect(dev[0], "radius-das")
740 addr = dev[0].p2p_interface_addr()
741 sta = hapd.get_sta(addr)
742 id = sta['dot1xAuthSessionId']
744 dict = pyrad.dictionary.Dictionary("dictionary.radius")
746 srv = pyrad.client.Client(server="127.0.0.1", acctport=3799,
747 secret="secret", dict=dict)
751 # hostapd does not currently support CoA-Request, so NAK is expected
752 logger.info("CoA-Request with matching Acct-Session-Id")
753 req = radius_das.CoAPacket(dict=dict, secret="secret",
755 Event_Timestamp=int(time.time()))
756 send_and_check_reply(srv, req, pyrad.packet.CoANAK, error_cause=405)
758 def test_radius_ipv6(dev, apdev):
759 """RADIUS connection over IPv6"""
761 params['ssid'] = 'as'
762 params['beacon_int'] = '2000'
763 params['radius_server_clients'] = 'auth_serv/radius_clients_ipv6.conf'
764 params['radius_server_ipv6'] = '1'
765 params['radius_server_auth_port'] = '18129'
766 params['radius_server_acct_port'] = '18139'
767 params['eap_server'] = '1'
768 params['eap_user_file'] = 'auth_serv/eap_user.conf'
769 params['ca_cert'] = 'auth_serv/ca.pem'
770 params['server_cert'] = 'auth_serv/server.pem'
771 params['private_key'] = 'auth_serv/server.key'
772 hostapd.add_ap(apdev[1], params)
774 params = hostapd.wpa2_eap_params(ssid="radius-ipv6")
775 params['auth_server_addr'] = "::0"
776 params['auth_server_port'] = "18129"
777 params['acct_server_addr'] = "::0"
778 params['acct_server_port'] = "18139"
779 params['acct_server_shared_secret'] = "radius"
780 params['own_ip_addr'] = "::0"
781 hostapd.add_ap(apdev[0], params)
782 connect(dev[0], "radius-ipv6")
784 def test_radius_macacl(dev, apdev):
786 params = hostapd.radius_params()
787 params["ssid"] = "radius"
788 params["macaddr_acl"] = "2"
789 hostapd.add_ap(apdev[0], params)
790 dev[0].connect("radius", key_mgmt="NONE", scan_freq="2412")
792 def test_radius_macacl_acct(dev, apdev):
793 """RADIUS MAC ACL and accounting enabled"""
794 params = hostapd.radius_params()
795 params["ssid"] = "radius"
796 params["macaddr_acl"] = "2"
797 params['acct_server_addr'] = "127.0.0.1"
798 params['acct_server_port'] = "1813"
799 params['acct_server_shared_secret'] = "radius"
800 hostapd.add_ap(apdev[0], params)
801 dev[0].connect("radius", key_mgmt="NONE", scan_freq="2412")
802 dev[1].connect("radius", key_mgmt="NONE", scan_freq="2412")
803 dev[1].request("DISCONNECT")
804 dev[1].wait_disconnected()
805 dev[1].request("RECONNECT")
807 def test_radius_failover(dev, apdev):
808 """RADIUS Authentication and Accounting server failover"""
809 subprocess.call(['ip', 'ro', 'replace', '192.168.213.17', 'dev', 'lo'])
810 as_hapd = hostapd.Hostapd("as")
811 as_mib_start = as_hapd.get_mib(param="radius_server")
812 params = hostapd.wpa2_eap_params(ssid="radius-failover")
813 params["auth_server_addr"] = "192.168.213.17"
814 params["auth_server_port"] = "1812"
815 params["auth_server_shared_secret"] = "testing"
816 params['acct_server_addr'] = "192.168.213.17"
817 params['acct_server_port'] = "1813"
818 params['acct_server_shared_secret'] = "testing"
819 params['radius_retry_primary_interval'] = "20"
820 hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
821 hapd.set("auth_server_addr", "127.0.0.1")
822 hapd.set("auth_server_port", "1812")
823 hapd.set("auth_server_shared_secret", "radius")
824 hapd.set('acct_server_addr', "127.0.0.1")
825 hapd.set('acct_server_port', "1813")
826 hapd.set('acct_server_shared_secret', "radius")
828 ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=30)
830 raise Exception("AP startup timed out")
831 if "AP-ENABLED" not in ev:
832 raise Exception("AP startup failed")
833 start = os.times()[4]
836 subprocess.call(['ip', 'ro', 'replace', 'prohibit', '192.168.213.17'])
837 dev[0].request("SET EAPOL::authPeriod 5")
838 connect(dev[0], "radius-failover", wait_connect=False)
839 dev[0].wait_connected(timeout=20)
841 dev[0].request("SET EAPOL::authPeriod 30")
842 subprocess.call(['ip', 'ro', 'del', '192.168.213.17'])
844 as_mib_end = as_hapd.get_mib(param="radius_server")
845 req_s = int(as_mib_start['radiusAccServTotalRequests'])
846 req_e = int(as_mib_end['radiusAccServTotalRequests'])
848 raise Exception("Unexpected RADIUS server acct MIB value")
852 subprocess.call(['ip', 'ro', 'replace', 'prohibit', '192.168.213.17'])
853 dev[1].request("SET EAPOL::authPeriod 5")
855 time.sleep(21 - (end - start))
856 connect(dev[1], "radius-failover", wait_connect=False)
857 dev[1].wait_connected(timeout=20)
859 dev[1].request("SET EAPOL::authPeriod 30")
860 subprocess.call(['ip', 'ro', 'del', '192.168.213.17'])
862 def run_pyrad_server(srv, t_events):
863 srv.RunWithStop(t_events)
865 def test_radius_protocol(dev, apdev):
866 """RADIUS Authentication protocol tests with a fake server"""
870 import pyrad.dictionary
872 raise HwsimSkip("No pyrad modules available")
874 class TestServer(pyrad.server.Server):
875 def _HandleAuthPacket(self, pkt):
876 pyrad.server.Server._HandleAuthPacket(self, pkt)
877 logger.info("Received authentication request")
878 reply = self.CreateReplyPacket(pkt)
879 reply.code = pyrad.packet.AccessAccept
880 if self.t_events['msg_auth'].is_set():
881 logger.info("Add Message-Authenticator")
882 if self.t_events['wrong_secret'].is_set():
883 logger.info("Use incorrect RADIUS shared secret")
887 hmac_obj = hmac.new(pw)
888 hmac_obj.update(struct.pack("B", reply.code))
889 hmac_obj.update(struct.pack("B", reply.id))
892 reply.AddAttribute("Message-Authenticator",
893 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
894 attrs = reply._PktEncodeAttributes()
897 flen = 4 + 16 + len(attrs)
898 hmac_obj.update(struct.pack(">H", flen))
899 hmac_obj.update(pkt.authenticator)
900 hmac_obj.update(attrs)
901 if self.t_events['double_msg_auth'].is_set():
902 logger.info("Include two Message-Authenticator attributes")
905 reply.AddAttribute("Message-Authenticator", hmac_obj.digest())
906 self.SendReplyPacket(pkt.fd, reply)
908 def RunWithStop(self, t_events):
909 self._poll = select.poll()
911 self._PrepareSockets()
912 self.t_events = t_events
914 while not t_events['stop'].is_set():
915 for (fd, event) in self._poll.poll(1000):
916 if event == select.POLLIN:
918 fdo = self._fdmap[fd]
919 self._ProcessInput(fdo)
920 except pyrad.server.ServerPacketError as err:
921 logger.info("pyrad server dropping packet: " + str(err))
922 except pyrad.packet.PacketError as err:
923 logger.info("pyrad server received invalid packet: " + str(err))
925 logger.error("Unexpected event in pyrad server main loop")
927 srv = TestServer(dict=pyrad.dictionary.Dictionary("dictionary.radius"),
928 authport=18138, acctport=18139)
929 srv.hosts["127.0.0.1"] = pyrad.server.RemoteHost("127.0.0.1",
932 srv.BindToAddress("")
934 t_events['stop'] = threading.Event()
935 t_events['msg_auth'] = threading.Event()
936 t_events['wrong_secret'] = threading.Event()
937 t_events['double_msg_auth'] = threading.Event()
938 t = threading.Thread(target=run_pyrad_server, args=(srv, t_events))
942 params = hostapd.wpa2_eap_params(ssid="radius-test")
943 params['auth_server_port'] = "18138"
944 hapd = hostapd.add_ap(apdev[0], params)
945 connect(dev[0], "radius-test", wait_connect=False)
946 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=15)
948 raise Exception("Timeout on EAP start")
950 dev[0].request("REMOVE_NETWORK all")
952 dev[0].dump_monitor()
953 t_events['msg_auth'].set()
954 t_events['wrong_secret'].set()
955 connect(dev[0], "radius-test", wait_connect=False)
957 dev[0].request("REMOVE_NETWORK all")
959 dev[0].dump_monitor()
960 t_events['wrong_secret'].clear()
961 connect(dev[0], "radius-test", wait_connect=False)
963 dev[0].request("REMOVE_NETWORK all")
965 dev[0].dump_monitor()
966 t_events['double_msg_auth'].set()
967 connect(dev[0], "radius-test", wait_connect=False)
970 t_events['stop'].set()
973 def test_radius_psk(dev, apdev):
974 """WPA2 with PSK from RADIUS"""
978 import pyrad.dictionary
980 raise HwsimSkip("No pyrad modules available")
982 class TestServer(pyrad.server.Server):
983 def _HandleAuthPacket(self, pkt):
984 pyrad.server.Server._HandleAuthPacket(self, pkt)
985 logger.info("Received authentication request")
986 reply = self.CreateReplyPacket(pkt)
987 reply.code = pyrad.packet.AccessAccept
989 secret = reply.secret
990 if self.t_events['long'].is_set():
991 p = b'\x10' + "0123456789abcdef" + 15 * b'\x00'
992 b = hashlib.md5(secret + pkt.authenticator + a).digest()
993 pp = bytearray(p[0:16])
995 cc = bytearray(pp[i] ^ bb[i] for i in range(len(bb)))
997 b = hashlib.md5(reply.secret + bytes(cc)).digest()
998 pp = bytearray(p[16:32])
1000 cc += bytearray(pp[i] ^ bb[i] for i in range(len(bb)))
1002 data = '\x00' + a + bytes(cc)
1004 p = b'\x08' + "12345678" + 7 * b'\x00'
1005 b = hashlib.md5(secret + pkt.authenticator + a).digest()
1008 cc = bytearray(pp[i] ^ bb[i] for i in range(len(bb)))
1009 data = '\x00' + a + bytes(cc)
1010 reply.AddAttribute("Tunnel-Password", data)
1011 self.SendReplyPacket(pkt.fd, reply)
1013 def RunWithStop(self, t_events):
1014 self._poll = select.poll()
1016 self._PrepareSockets()
1017 self.t_events = t_events
1019 while not t_events['stop'].is_set():
1020 for (fd, event) in self._poll.poll(1000):
1021 if event == select.POLLIN:
1023 fdo = self._fdmap[fd]
1024 self._ProcessInput(fdo)
1025 except pyrad.server.ServerPacketError as err:
1026 logger.info("pyrad server dropping packet: " + str(err))
1027 except pyrad.packet.PacketError as err:
1028 logger.info("pyrad server received invalid packet: " + str(err))
1030 logger.error("Unexpected event in pyrad server main loop")
1032 srv = TestServer(dict=pyrad.dictionary.Dictionary("dictionary.radius"),
1033 authport=18138, acctport=18139)
1034 srv.hosts["127.0.0.1"] = pyrad.server.RemoteHost("127.0.0.1",
1037 srv.BindToAddress("")
1039 t_events['stop'] = threading.Event()
1040 t_events['long'] = threading.Event()
1041 t = threading.Thread(target=run_pyrad_server, args=(srv, t_events))
1045 ssid = "test-wpa2-psk"
1046 params = hostapd.radius_params()
1047 params['ssid'] = ssid
1049 params["wpa_key_mgmt"] = "WPA-PSK"
1050 params["rsn_pairwise"] = "CCMP"
1051 params['macaddr_acl'] = '2'
1052 params['wpa_psk_radius'] = '2'
1053 params['auth_server_port'] = "18138"
1054 hapd = hostapd.add_ap(apdev[0], params)
1055 dev[0].connect(ssid, psk="12345678", scan_freq="2412")
1056 t_events['long'].set()
1057 dev[1].connect(ssid, psk="0123456789abcdef", scan_freq="2412")
1059 t_events['stop'].set()
1062 def test_radius_psk_invalid(dev, apdev):
1063 """WPA2 with invalid PSK from RADIUS"""
1067 import pyrad.dictionary
1069 raise HwsimSkip("No pyrad modules available")
1071 class TestServer(pyrad.server.Server):
1072 def _HandleAuthPacket(self, pkt):
1073 pyrad.server.Server._HandleAuthPacket(self, pkt)
1074 logger.info("Received authentication request")
1075 reply = self.CreateReplyPacket(pkt)
1076 reply.code = pyrad.packet.AccessAccept
1078 secret = reply.secret
1079 p = b'\x07' + "1234567" + 8 * b'\x00'
1080 b = hashlib.md5(secret + pkt.authenticator + a).digest()
1083 cc = bytearray(pp[i] ^ bb[i] for i in range(len(bb)))
1084 data = '\x00' + a + bytes(cc)
1085 reply.AddAttribute("Tunnel-Password", data)
1086 self.SendReplyPacket(pkt.fd, reply)
1088 def RunWithStop(self, t_events):
1089 self._poll = select.poll()
1091 self._PrepareSockets()
1092 self.t_events = t_events
1094 while not t_events['stop'].is_set():
1095 for (fd, event) in self._poll.poll(1000):
1096 if event == select.POLLIN:
1098 fdo = self._fdmap[fd]
1099 self._ProcessInput(fdo)
1100 except pyrad.server.ServerPacketError as err:
1101 logger.info("pyrad server dropping packet: " + str(err))
1102 except pyrad.packet.PacketError as err:
1103 logger.info("pyrad server received invalid packet: " + str(err))
1105 logger.error("Unexpected event in pyrad server main loop")
1107 srv = TestServer(dict=pyrad.dictionary.Dictionary("dictionary.radius"),
1108 authport=18138, acctport=18139)
1109 srv.hosts["127.0.0.1"] = pyrad.server.RemoteHost("127.0.0.1",
1112 srv.BindToAddress("")
1114 t_events['stop'] = threading.Event()
1115 t = threading.Thread(target=run_pyrad_server, args=(srv, t_events))
1119 ssid = "test-wpa2-psk"
1120 params = hostapd.radius_params()
1121 params['ssid'] = ssid
1123 params["wpa_key_mgmt"] = "WPA-PSK"
1124 params["rsn_pairwise"] = "CCMP"
1125 params['macaddr_acl'] = '2'
1126 params['wpa_psk_radius'] = '2'
1127 params['auth_server_port'] = "18138"
1128 hapd = hostapd.add_ap(apdev[0], params)
1129 dev[0].connect(ssid, psk="12345678", scan_freq="2412",
1133 t_events['stop'].set()
1136 def test_radius_auth_force_client_addr(dev, apdev):
1137 """RADIUS client address specified"""
1138 params = hostapd.wpa2_eap_params(ssid="radius-auth")
1139 params['radius_client_addr'] = "127.0.0.1"
1140 hapd = hostapd.add_ap(apdev[0], params)
1141 connect(dev[0], "radius-auth")
1144 def test_radius_auth_force_invalid_client_addr(dev, apdev):
1145 """RADIUS client address specified and invalid address"""
1146 params = hostapd.wpa2_eap_params(ssid="radius-auth")
1147 #params['radius_client_addr'] = "10.11.12.14"
1148 params['radius_client_addr'] = "1::2"
1149 hapd = hostapd.add_ap(apdev[0], params)
1150 connect(dev[0], "radius-auth", wait_connect=False)
1151 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"])
1153 raise Exception("Timeout on EAP start")
1154 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
1156 raise Exception("Unexpected connection")
1158 def add_message_auth(req):
1159 req.authenticator = req.CreateAuthenticator()
1160 hmac_obj = hmac.new(req.secret)
1161 hmac_obj.update(struct.pack("B", req.code))
1162 hmac_obj.update(struct.pack("B", req.id))
1164 # request attributes
1165 req.AddAttribute("Message-Authenticator",
1166 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
1167 attrs = req._PktEncodeAttributes()
1170 flen = 4 + 16 + len(attrs)
1171 hmac_obj.update(struct.pack(">H", flen))
1172 hmac_obj.update(req.authenticator)
1173 hmac_obj.update(attrs)
1175 req.AddAttribute("Message-Authenticator", hmac_obj.digest())
1177 def test_radius_server_failures(dev, apdev):
1178 """RADIUS server failure cases"""
1182 import pyrad.dictionary
1184 raise HwsimSkip("No pyrad modules available")
1186 dict = pyrad.dictionary.Dictionary("dictionary.radius")
1187 client = pyrad.client.Client(server="127.0.0.1", authport=1812,
1188 secret="radius", dict=dict)
1193 req = client.CreateAuthPacket(code=pyrad.packet.AccessRequest,
1195 req['State'] = 'foo-state'
1196 add_message_auth(req)
1197 reply = client.SendPacket(req)
1198 if reply.code != pyrad.packet.AccessReject:
1199 raise Exception("Unexpected RADIUS response code " + str(reply.code))
1202 req = client.CreateAuthPacket(code=pyrad.packet.AccessRequest,
1204 add_message_auth(req)
1206 reply = client.SendPacket(req)
1207 raise Exception("Unexpected response")
1208 except pyrad.client.Timeout:
1211 def test_ap_vlan_wpa2_psk_radius_required(dev, apdev):
1212 """AP VLAN with WPA2-PSK and RADIUS attributes required"""
1216 import pyrad.dictionary
1218 raise HwsimSkip("No pyrad modules available")
1220 class TestServer(pyrad.server.Server):
1221 def _HandleAuthPacket(self, pkt):
1222 pyrad.server.Server._HandleAuthPacket(self, pkt)
1223 logger.info("Received authentication request")
1224 reply = self.CreateReplyPacket(pkt)
1225 reply.code = pyrad.packet.AccessAccept
1226 secret = reply.secret
1227 if self.t_events['extra'].is_set():
1228 reply.AddAttribute("Chargeable-User-Identity", "test-cui")
1229 reply.AddAttribute("User-Name", "test-user")
1230 if self.t_events['long'].is_set():
1231 reply.AddAttribute("Tunnel-Type", 13)
1232 reply.AddAttribute("Tunnel-Medium-Type", 6)
1233 reply.AddAttribute("Tunnel-Private-Group-ID", "1")
1234 self.SendReplyPacket(pkt.fd, reply)
1236 def RunWithStop(self, t_events):
1237 self._poll = select.poll()
1239 self._PrepareSockets()
1240 self.t_events = t_events
1242 while not t_events['stop'].is_set():
1243 for (fd, event) in self._poll.poll(1000):
1244 if event == select.POLLIN:
1246 fdo = self._fdmap[fd]
1247 self._ProcessInput(fdo)
1248 except pyrad.server.ServerPacketError as err:
1249 logger.info("pyrad server dropping packet: " + str(err))
1250 except pyrad.packet.PacketError as err:
1251 logger.info("pyrad server received invalid packet: " + str(err))
1253 logger.error("Unexpected event in pyrad server main loop")
1255 srv = TestServer(dict=pyrad.dictionary.Dictionary("dictionary.radius"),
1256 authport=18138, acctport=18139)
1257 srv.hosts["127.0.0.1"] = pyrad.server.RemoteHost("127.0.0.1",
1260 srv.BindToAddress("")
1262 t_events['stop'] = threading.Event()
1263 t_events['long'] = threading.Event()
1264 t_events['extra'] = threading.Event()
1265 t = threading.Thread(target=run_pyrad_server, args=(srv, t_events))
1269 ssid = "test-wpa2-psk"
1270 params = hostapd.radius_params()
1271 params['ssid'] = ssid
1273 params["wpa_key_mgmt"] = "WPA-PSK"
1274 params["rsn_pairwise"] = "CCMP"
1275 params['macaddr_acl'] = '2'
1276 params['dynamic_vlan'] = "2"
1277 params['wpa_passphrase'] = '0123456789abcdefghi'
1278 params['auth_server_port'] = "18138"
1279 hapd = hostapd.add_ap(apdev[0], params)
1281 logger.info("connecting without VLAN")
1282 dev[0].connect(ssid, psk="0123456789abcdefghi", scan_freq="2412",
1284 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
1285 "CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=20)
1287 raise Exception("Timeout on connection attempt")
1288 if "CTRL-EVENT-CONNECTED" in ev:
1289 raise Exception("Unexpected success without vlan parameters")
1290 logger.info("connecting without VLAN failed as expected")
1292 logger.info("connecting without VLAN (CUI/User-Name)")
1293 t_events['extra'].set()
1294 dev[1].connect(ssid, psk="0123456789abcdefghi", scan_freq="2412",
1296 ev = dev[1].wait_event(["CTRL-EVENT-CONNECTED",
1297 "CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=20)
1299 raise Exception("Timeout on connection attempt")
1300 if "CTRL-EVENT-CONNECTED" in ev:
1301 raise Exception("Unexpected success without vlan parameters(2)")
1302 logger.info("connecting without VLAN failed as expected(2)")
1303 t_events['extra'].clear()
1305 t_events['long'].set()
1306 logger.info("connecting with VLAN")
1307 dev[2].connect(ssid, psk="0123456789abcdefghi", scan_freq="2412",
1309 ev = dev[2].wait_event(["CTRL-EVENT-CONNECTED",
1310 "CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=20)
1312 raise Exception("Timeout on connection attempt")
1313 if "CTRL-EVENT-SSID-TEMP-DISABLED" in ev:
1314 raise Exception("Unexpected failure with vlan parameters")
1315 logger.info("connecting with VLAN succeeded as expected")
1317 t_events['stop'].set()
1320 def test_radius_mppe_failure(dev, apdev):
1321 """RADIUS failure when adding MPPE keys"""
1322 params = { "ssid": "as", "beacon_int": "2000",
1323 "radius_server_clients": "auth_serv/radius_clients.conf",
1324 "radius_server_auth_port": '18127',
1326 "eap_user_file": "auth_serv/eap_user.conf",
1327 "ca_cert": "auth_serv/ca.pem",
1328 "server_cert": "auth_serv/server.pem",
1329 "private_key": "auth_serv/server.key" }
1330 authsrv = hostapd.add_ap(apdev[1], params)
1332 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
1333 params['auth_server_port'] = "18127"
1334 hapd = hostapd.add_ap(apdev[0], params)
1336 with fail_test(authsrv, 1, "os_get_random;radius_msg_add_mppe_keys"):
1337 dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
1338 identity="user", anonymous_identity="ttls",
1339 password="password",
1340 ca_cert="auth_serv/ca.pem", phase2="autheap=GTC",
1341 wait_connect=False, scan_freq="2412")
1342 dev[0].wait_disconnected()
1343 dev[0].request("REMOVE_NETWORK all")