]>
git.ipfire.org Git - thirdparty/hostap.git/blob - tests/hwsim/test_radius.py
2 # Copyright (c) 2013-2015, Jouni Malinen <j@w1.fi>
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
11 logger
= logging
.getLogger()
20 from utils
import HwsimSkip
, require_under_vm
, skip_with_fips
21 from test_ap_hs20
import build_dhcp_ack
22 from test_ap_ft
import ft_params1
24 def connect(dev
, ssid
, wait_connect
=True):
25 dev
.connect(ssid
, key_mgmt
="WPA-EAP", scan_freq
="2412",
26 eap
="PSK", identity
="psk.user@example.com",
27 password_hex
="0123456789abcdef0123456789abcdef",
28 wait_connect
=wait_connect
)
30 def test_radius_auth_unreachable(dev
, apdev
):
31 """RADIUS Authentication server unreachable"""
32 params
= hostapd
.wpa2_eap_params(ssid
="radius-auth")
33 params
['auth_server_port'] = "18139"
34 hostapd
.add_ap(apdev
[0], params
)
35 hapd
= hostapd
.Hostapd(apdev
[0]['ifname'])
36 connect(dev
[0], "radius-auth", wait_connect
=False)
37 ev
= dev
[0].wait_event(["CTRL-EVENT-EAP-STARTED"])
39 raise Exception("Timeout on EAP start")
40 logger
.info("Checking for RADIUS retries")
43 if "radiusAuthClientAccessRequests" not in mib
:
44 raise Exception("Missing MIB fields")
45 if int(mib
["radiusAuthClientAccessRetransmissions"]) < 1:
46 raise Exception("Missing RADIUS Authentication retransmission")
47 if int(mib
["radiusAuthClientPendingRequests"]) < 1:
48 raise Exception("Missing pending RADIUS Authentication request")
50 def test_radius_auth_unreachable2(dev
, apdev
):
51 """RADIUS Authentication server unreachable (2)"""
52 subprocess
.call(['ip', 'ro', 'replace', '192.168.213.17', 'dev', 'lo'])
53 params
= hostapd
.wpa2_eap_params(ssid
="radius-auth")
54 params
['auth_server_addr'] = "192.168.213.17"
55 params
['auth_server_port'] = "18139"
56 hostapd
.add_ap(apdev
[0], params
)
57 hapd
= hostapd
.Hostapd(apdev
[0]['ifname'])
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 hostapd
.add_ap(apdev
[0], params
)
77 hapd
= hostapd
.Hostapd(apdev
[0]['ifname'])
78 connect(dev
[0], "radius-auth", wait_connect
=False)
79 ev
= dev
[0].wait_event(["CTRL-EVENT-EAP-STARTED"])
81 raise Exception("Timeout on EAP start")
82 subprocess
.call(['ip', 'ro', 'del', 'blackhole', '192.168.213.18'])
84 dev
[0].request("DISCONNECT")
85 hapd
.set('auth_server_addr_replace', '127.0.0.1')
86 dev
[0].request("RECONNECT")
88 dev
[0].wait_connected()
90 def test_radius_acct_unreachable(dev
, apdev
):
91 """RADIUS Accounting server unreachable"""
92 params
= hostapd
.wpa2_eap_params(ssid
="radius-acct")
93 params
['acct_server_addr'] = "127.0.0.1"
94 params
['acct_server_port'] = "18139"
95 params
['acct_server_shared_secret'] = "radius"
96 hostapd
.add_ap(apdev
[0], params
)
97 hapd
= hostapd
.Hostapd(apdev
[0]['ifname'])
98 connect(dev
[0], "radius-acct")
99 logger
.info("Checking for RADIUS retries")
102 if "radiusAccClientRetransmissions" not in mib
:
103 raise Exception("Missing MIB fields")
104 if int(mib
["radiusAccClientRetransmissions"]) < 2:
105 raise Exception("Missing RADIUS Accounting retransmissions")
106 if int(mib
["radiusAccClientPendingRequests"]) < 2:
107 raise Exception("Missing pending RADIUS Accounting requests")
109 def test_radius_acct_unreachable2(dev
, apdev
):
110 """RADIUS Accounting server unreachable(2)"""
111 subprocess
.call(['ip', 'ro', 'replace', '192.168.213.17', 'dev', 'lo'])
112 params
= hostapd
.wpa2_eap_params(ssid
="radius-acct")
113 params
['acct_server_addr'] = "192.168.213.17"
114 params
['acct_server_port'] = "18139"
115 params
['acct_server_shared_secret'] = "radius"
116 hostapd
.add_ap(apdev
[0], params
)
117 hapd
= hostapd
.Hostapd(apdev
[0]['ifname'])
118 subprocess
.call(['ip', 'ro', 'del', '192.168.213.17', 'dev', 'lo'])
119 connect(dev
[0], "radius-acct")
120 logger
.info("Checking for RADIUS retries")
123 if "radiusAccClientRetransmissions" not in mib
:
124 raise Exception("Missing MIB fields")
125 if int(mib
["radiusAccClientRetransmissions"]) < 1 and int(mib
["radiusAccClientPendingRequests"]) < 1:
126 raise Exception("Missing pending or retransmitted RADIUS Accounting requests")
128 def test_radius_acct_unreachable3(dev
, apdev
):
129 """RADIUS Accounting server initially unreachable, but then available"""
131 subprocess
.call(['ip', 'ro', 'replace', 'blackhole', '192.168.213.18'])
132 as_hapd
= hostapd
.Hostapd("as")
133 as_mib_start
= as_hapd
.get_mib(param
="radius_server")
134 params
= hostapd
.wpa2_eap_params(ssid
="radius-acct")
135 params
['acct_server_addr'] = "192.168.213.18"
136 params
['acct_server_port'] = "1813"
137 params
['acct_server_shared_secret'] = "radius"
138 hostapd
.add_ap(apdev
[0], params
)
139 hapd
= hostapd
.Hostapd(apdev
[0]['ifname'])
140 connect(dev
[0], "radius-acct")
141 subprocess
.call(['ip', 'ro', 'del', 'blackhole', '192.168.213.18'])
143 dev
[0].request("DISCONNECT")
144 hapd
.set('acct_server_addr_replace', '127.0.0.1')
145 dev
[0].request("RECONNECT")
146 dev
[0].wait_connected()
148 as_mib_end
= as_hapd
.get_mib(param
="radius_server")
149 req_s
= int(as_mib_start
['radiusAccServTotalResponses'])
150 req_e
= int(as_mib_end
['radiusAccServTotalResponses'])
152 raise Exception("Unexpected RADIUS server acct MIB value")
154 def test_radius_acct_unreachable4(dev
, apdev
):
155 """RADIUS Accounting server unreachable and multiple STAs"""
156 params
= hostapd
.wpa2_eap_params(ssid
="radius-acct")
157 params
['acct_server_addr'] = "127.0.0.1"
158 params
['acct_server_port'] = "18139"
159 params
['acct_server_shared_secret'] = "radius"
160 hostapd
.add_ap(apdev
[0], params
)
161 hapd
= hostapd
.Hostapd(apdev
[0]['ifname'])
163 connect(dev
[0], "radius-acct")
164 dev
[0].request("REMOVE_NETWORK all")
165 dev
[0].wait_disconnected()
167 def test_radius_acct(dev
, apdev
):
168 """RADIUS Accounting"""
169 as_hapd
= hostapd
.Hostapd("as")
170 as_mib_start
= as_hapd
.get_mib(param
="radius_server")
171 params
= hostapd
.wpa2_eap_params(ssid
="radius-acct")
172 params
['acct_server_addr'] = "127.0.0.1"
173 params
['acct_server_port'] = "1813"
174 params
['acct_server_shared_secret'] = "radius"
175 params
['radius_auth_req_attr'] = [ "126:s:Operator", "77:s:testing" ]
176 params
['radius_acct_req_attr'] = [ "126:s:Operator", "77:s:testing" ]
177 hostapd
.add_ap(apdev
[0], params
)
178 hapd
= hostapd
.Hostapd(apdev
[0]['ifname'])
179 connect(dev
[0], "radius-acct")
180 dev
[1].connect("radius-acct", key_mgmt
="WPA-EAP", scan_freq
="2412",
181 eap
="PAX", identity
="test-class",
182 password_hex
="0123456789abcdef0123456789abcdef")
183 dev
[2].connect("radius-acct", key_mgmt
="WPA-EAP",
184 eap
="GPSK", identity
="gpsk-cui",
185 password
="abcdefghijklmnop0123456789abcdef",
187 logger
.info("Checking for RADIUS counters")
191 if int(mib
['radiusAccClientResponses']) >= 3:
196 raise Exception("Did not receive Accounting-Response packets")
198 if int(mib
['radiusAccClientRetransmissions']) > 0:
199 raise Exception("Unexpected Accounting-Request retransmission")
201 as_mib_end
= as_hapd
.get_mib(param
="radius_server")
203 req_s
= int(as_mib_start
['radiusAccServTotalRequests'])
204 req_e
= int(as_mib_end
['radiusAccServTotalRequests'])
205 if req_e
< req_s
+ 2:
206 raise Exception("Unexpected RADIUS server acct MIB value")
208 acc_s
= int(as_mib_start
['radiusAuthServAccessAccepts'])
209 acc_e
= int(as_mib_end
['radiusAuthServAccessAccepts'])
210 if acc_e
< acc_s
+ 1:
211 raise Exception("Unexpected RADIUS server auth MIB value")
213 def test_radius_acct_non_ascii_ssid(dev
, apdev
):
214 """RADIUS Accounting and non-ASCII SSID"""
215 params
= hostapd
.wpa2_eap_params()
216 params
['acct_server_addr'] = "127.0.0.1"
217 params
['acct_server_port'] = "1813"
218 params
['acct_server_shared_secret'] = "radius"
219 ssid2
= "740665007374"
220 params
['ssid2'] = ssid2
221 hostapd
.add_ap(apdev
[0], params
)
222 dev
[0].connect(ssid2
=ssid2
, key_mgmt
="WPA-EAP", scan_freq
="2412",
223 eap
="PSK", identity
="psk.user@example.com",
224 password_hex
="0123456789abcdef0123456789abcdef")
226 def test_radius_acct_pmksa_caching(dev
, apdev
):
227 """RADIUS Accounting with PMKSA caching"""
228 as_hapd
= hostapd
.Hostapd("as")
229 as_mib_start
= as_hapd
.get_mib(param
="radius_server")
230 params
= hostapd
.wpa2_eap_params(ssid
="radius-acct")
231 params
['acct_server_addr'] = "127.0.0.1"
232 params
['acct_server_port'] = "1813"
233 params
['acct_server_shared_secret'] = "radius"
234 hapd
= hostapd
.add_ap(apdev
[0], params
)
235 connect(dev
[0], "radius-acct")
236 dev
[1].connect("radius-acct", key_mgmt
="WPA-EAP", scan_freq
="2412",
237 eap
="PAX", identity
="test-class",
238 password_hex
="0123456789abcdef0123456789abcdef")
239 for d
in [ dev
[0], dev
[1] ]:
240 d
.request("REASSOCIATE")
241 d
.wait_connected(timeout
=15, error
="Reassociation timed out")
246 if int(mib
['radiusAccClientResponses']) >= 4:
251 raise Exception("Did not receive Accounting-Response packets")
253 if int(mib
['radiusAccClientRetransmissions']) > 0:
254 raise Exception("Unexpected Accounting-Request retransmission")
256 as_mib_end
= as_hapd
.get_mib(param
="radius_server")
258 req_s
= int(as_mib_start
['radiusAccServTotalRequests'])
259 req_e
= int(as_mib_end
['radiusAccServTotalRequests'])
260 if req_e
< req_s
+ 2:
261 raise Exception("Unexpected RADIUS server acct MIB value")
263 acc_s
= int(as_mib_start
['radiusAuthServAccessAccepts'])
264 acc_e
= int(as_mib_end
['radiusAuthServAccessAccepts'])
265 if acc_e
< acc_s
+ 1:
266 raise Exception("Unexpected RADIUS server auth MIB value")
268 def test_radius_acct_interim(dev
, apdev
):
269 """RADIUS Accounting interim update"""
270 as_hapd
= hostapd
.Hostapd("as")
271 params
= hostapd
.wpa2_eap_params(ssid
="radius-acct")
272 params
['acct_server_addr'] = "127.0.0.1"
273 params
['acct_server_port'] = "1813"
274 params
['acct_server_shared_secret'] = "radius"
275 params
['radius_acct_interim_interval'] = "1"
276 hostapd
.add_ap(apdev
[0], params
)
277 hapd
= hostapd
.Hostapd(apdev
[0]['ifname'])
278 connect(dev
[0], "radius-acct")
279 logger
.info("Checking for RADIUS counters")
280 as_mib_start
= as_hapd
.get_mib(param
="radius_server")
282 as_mib_end
= as_hapd
.get_mib(param
="radius_server")
283 req_s
= int(as_mib_start
['radiusAccServTotalRequests'])
284 req_e
= int(as_mib_end
['radiusAccServTotalRequests'])
285 if req_e
< req_s
+ 3:
286 raise Exception("Unexpected RADIUS server acct MIB value")
288 def test_radius_acct_interim_unreachable(dev
, apdev
):
289 """RADIUS Accounting interim update with unreachable server"""
290 params
= hostapd
.wpa2_eap_params(ssid
="radius-acct")
291 params
['acct_server_addr'] = "127.0.0.1"
292 params
['acct_server_port'] = "18139"
293 params
['acct_server_shared_secret'] = "radius"
294 params
['radius_acct_interim_interval'] = "1"
295 hapd
= hostapd
.add_ap(apdev
[0], params
)
296 start
= hapd
.get_mib()
297 connect(dev
[0], "radius-acct")
298 logger
.info("Waiting for interium accounting updates")
301 req_s
= int(start
['radiusAccClientTimeouts'])
302 req_e
= int(end
['radiusAccClientTimeouts'])
303 if req_e
< req_s
+ 2:
304 raise Exception("Unexpected RADIUS server acct MIB value")
306 def test_radius_acct_interim_unreachable2(dev
, apdev
):
307 """RADIUS Accounting interim update with unreachable server (retry)"""
308 params
= hostapd
.wpa2_eap_params(ssid
="radius-acct")
309 params
['acct_server_addr'] = "127.0.0.1"
310 params
['acct_server_port'] = "18139"
311 params
['acct_server_shared_secret'] = "radius"
312 # Use long enough interim update interval to allow RADIUS retransmission
313 # case (3 seconds) to trigger first.
314 params
['radius_acct_interim_interval'] = "4"
315 hapd
= hostapd
.add_ap(apdev
[0], params
)
316 start
= hapd
.get_mib()
317 connect(dev
[0], "radius-acct")
318 logger
.info("Waiting for interium accounting updates")
321 req_s
= int(start
['radiusAccClientTimeouts'])
322 req_e
= int(end
['radiusAccClientTimeouts'])
323 if req_e
< req_s
+ 2:
324 raise Exception("Unexpected RADIUS server acct MIB value")
326 def test_radius_acct_ipaddr(dev
, apdev
):
327 """RADIUS Accounting and Framed-IP-Address"""
329 _test_radius_acct_ipaddr(dev
, apdev
)
331 subprocess
.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
332 stderr
=open('/dev/null', 'w'))
333 subprocess
.call(['brctl', 'delbr', 'ap-br0'],
334 stderr
=open('/dev/null', 'w'))
336 def _test_radius_acct_ipaddr(dev
, apdev
):
337 params
= { "ssid": "radius-acct-open",
338 'acct_server_addr': "127.0.0.1",
339 'acct_server_port': "1813",
340 'acct_server_shared_secret': "radius",
344 hapd
= hostapd
.add_ap(apdev
[0], params
, no_enable
=True)
348 # For now, do not report failures due to missing kernel support
349 raise HwsimSkip("Could not start hostapd - assume proxyarp not supported in kernel version")
350 bssid
= apdev
[0]['bssid']
352 subprocess
.call(['brctl', 'setfd', 'ap-br0', '0'])
353 subprocess
.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
355 dev
[0].connect("radius-acct-open", key_mgmt
="NONE", scan_freq
="2412")
356 addr0
= dev
[0].own_addr()
358 pkt
= build_dhcp_ack(dst_ll
="ff:ff:ff:ff:ff:ff", src_ll
=bssid
,
359 ip_src
="192.168.1.1", ip_dst
="255.255.255.255",
360 yiaddr
="192.168.1.123", chaddr
=addr0
)
361 if "OK" not in hapd
.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii
.hexlify(pkt
)):
362 raise Exception("DATA_TEST_FRAME failed")
364 dev
[0].request("DISCONNECT")
365 dev
[0].wait_disconnected()
368 def send_and_check_reply(srv
, req
, code
, error_cause
=0):
369 reply
= srv
.SendPacket(req
)
370 logger
.debug("RADIUS response from hostapd")
371 for i
in reply
.keys():
372 logger
.debug("%s: %s" % (i
, reply
[i
]))
373 if reply
.code
!= code
:
374 raise Exception("Unexpected response code")
376 if 'Error-Cause' not in reply
:
377 raise Exception("Missing Error-Cause")
378 if reply
['Error-Cause'][0] != error_cause
:
379 raise Exception("Unexpected Error-Cause: {}".format(reply
['Error-Cause']))
381 def test_radius_acct_psk(dev
, apdev
):
382 """RADIUS Accounting - PSK"""
383 as_hapd
= hostapd
.Hostapd("as")
384 params
= hostapd
.wpa2_params(ssid
="radius-acct", passphrase
="12345678")
385 params
['acct_server_addr'] = "127.0.0.1"
386 params
['acct_server_port'] = "1813"
387 params
['acct_server_shared_secret'] = "radius"
388 hapd
= hostapd
.add_ap(apdev
[0], params
)
389 dev
[0].connect("radius-acct", psk
="12345678", scan_freq
="2412")
391 def test_radius_acct_psk_sha256(dev
, apdev
):
392 """RADIUS Accounting - PSK SHA256"""
393 as_hapd
= hostapd
.Hostapd("as")
394 params
= hostapd
.wpa2_params(ssid
="radius-acct", passphrase
="12345678")
395 params
["wpa_key_mgmt"] = "WPA-PSK-SHA256"
396 params
['acct_server_addr'] = "127.0.0.1"
397 params
['acct_server_port'] = "1813"
398 params
['acct_server_shared_secret'] = "radius"
399 hapd
= hostapd
.add_ap(apdev
[0], params
)
400 dev
[0].connect("radius-acct", key_mgmt
="WPA-PSK-SHA256",
401 psk
="12345678", scan_freq
="2412")
403 def test_radius_acct_ft_psk(dev
, apdev
):
404 """RADIUS Accounting - FT-PSK"""
405 as_hapd
= hostapd
.Hostapd("as")
406 params
= ft_params1(ssid
="radius-acct", passphrase
="12345678")
407 params
['acct_server_addr'] = "127.0.0.1"
408 params
['acct_server_port'] = "1813"
409 params
['acct_server_shared_secret'] = "radius"
410 hapd
= hostapd
.add_ap(apdev
[0], params
)
411 dev
[0].connect("radius-acct", key_mgmt
="FT-PSK",
412 psk
="12345678", scan_freq
="2412")
414 def test_radius_acct_ieee8021x(dev
, apdev
):
415 """RADIUS Accounting - IEEE 802.1X"""
416 skip_with_fips(dev
[0])
417 as_hapd
= hostapd
.Hostapd("as")
418 params
= hostapd
.radius_params()
419 params
["ssid"] = "radius-acct-1x"
420 params
["ieee8021x"] = "1"
421 params
["wep_key_len_broadcast"] = "13"
422 params
["wep_key_len_unicast"] = "13"
423 params
['acct_server_addr'] = "127.0.0.1"
424 params
['acct_server_port'] = "1813"
425 params
['acct_server_shared_secret'] = "radius"
426 hapd
= hostapd
.add_ap(apdev
[0], params
)
427 dev
[0].connect("radius-acct-1x", key_mgmt
="IEEE8021X", eap
="PSK",
428 identity
="psk.user@example.com",
429 password_hex
="0123456789abcdef0123456789abcdef",
432 def test_radius_das_disconnect(dev
, apdev
):
433 """RADIUS Dynamic Authorization Extensions - Disconnect"""
437 import pyrad
.dictionary
440 raise HwsimSkip("No pyrad modules available")
442 params
= hostapd
.wpa2_eap_params(ssid
="radius-das")
443 params
['radius_das_port'] = "3799"
444 params
['radius_das_client'] = "127.0.0.1 secret"
445 params
['radius_das_require_event_timestamp'] = "1"
446 params
['own_ip_addr'] = "127.0.0.1"
447 params
['nas_identifier'] = "nas.example.com"
448 hapd
= hostapd
.add_ap(apdev
[0], params
)
449 connect(dev
[0], "radius-das")
450 addr
= dev
[0].p2p_interface_addr()
451 sta
= hapd
.get_sta(addr
)
452 id = sta
['dot1xAuthSessionId']
454 dict = pyrad
.dictionary
.Dictionary("dictionary.radius")
456 srv
= pyrad
.client
.Client(server
="127.0.0.1", acctport
=3799,
457 secret
="secret", dict=dict)
461 logger
.info("Disconnect-Request with incorrect secret")
462 req
= radius_das
.DisconnectPacket(dict=dict, secret
="incorrect",
464 NAS_Identifier
="localhost",
465 Event_Timestamp
=int(time
.time()))
468 reply
= srv
.SendPacket(req
)
469 raise Exception("Unexpected response to Disconnect-Request")
470 except pyrad
.client
.Timeout
:
471 logger
.info("Disconnect-Request with incorrect secret properly ignored")
473 logger
.info("Disconnect-Request without Event-Timestamp")
474 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
475 User_Name
="psk.user@example.com")
478 reply
= srv
.SendPacket(req
)
479 raise Exception("Unexpected response to Disconnect-Request")
480 except pyrad
.client
.Timeout
:
481 logger
.info("Disconnect-Request without Event-Timestamp properly ignored")
483 logger
.info("Disconnect-Request with non-matching Event-Timestamp")
484 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
485 User_Name
="psk.user@example.com",
486 Event_Timestamp
=123456789)
489 reply
= srv
.SendPacket(req
)
490 raise Exception("Unexpected response to Disconnect-Request")
491 except pyrad
.client
.Timeout
:
492 logger
.info("Disconnect-Request with non-matching Event-Timestamp properly ignored")
494 logger
.info("Disconnect-Request with unsupported attribute")
495 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
498 Event_Timestamp
=int(time
.time()))
499 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectNAK
, 401)
501 logger
.info("Disconnect-Request with invalid Calling-Station-Id")
502 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
504 Calling_Station_Id
="foo",
505 Event_Timestamp
=int(time
.time()))
506 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectNAK
, 407)
508 logger
.info("Disconnect-Request with mismatching User-Name")
509 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
511 Event_Timestamp
=int(time
.time()))
512 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectNAK
, 503)
514 logger
.info("Disconnect-Request with mismatching Calling-Station-Id")
515 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
516 Calling_Station_Id
="12:34:56:78:90:aa",
517 Event_Timestamp
=int(time
.time()))
518 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectNAK
, 503)
520 logger
.info("Disconnect-Request with mismatching Acct-Session-Id")
521 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
522 Acct_Session_Id
="12345678-87654321",
523 Event_Timestamp
=int(time
.time()))
524 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectNAK
, 503)
526 logger
.info("Disconnect-Request with mismatching Acct-Session-Id (len)")
527 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
528 Acct_Session_Id
="12345678",
529 Event_Timestamp
=int(time
.time()))
530 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectNAK
, 503)
532 logger
.info("Disconnect-Request with mismatching Acct-Multi-Session-Id")
533 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
534 Acct_Multi_Session_Id
="12345678+87654321",
535 Event_Timestamp
=int(time
.time()))
536 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectNAK
, 503)
538 logger
.info("Disconnect-Request with mismatching Acct-Multi-Session-Id (len)")
539 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
540 Acct_Multi_Session_Id
="12345678",
541 Event_Timestamp
=int(time
.time()))
542 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectNAK
, 503)
544 logger
.info("Disconnect-Request with no session identification attributes")
545 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
546 Event_Timestamp
=int(time
.time()))
547 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectNAK
, 503)
549 ev
= dev
[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout
=1)
551 raise Exception("Unexpected disconnection")
553 logger
.info("Disconnect-Request with mismatching NAS-IP-Address")
554 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
555 NAS_IP_Address
="192.168.3.4",
557 Event_Timestamp
=int(time
.time()))
558 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectNAK
, 403)
560 logger
.info("Disconnect-Request with mismatching NAS-Identifier")
561 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
562 NAS_Identifier
="unknown.example.com",
564 Event_Timestamp
=int(time
.time()))
565 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectNAK
, 403)
567 ev
= dev
[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout
=1)
569 raise Exception("Unexpected disconnection")
571 logger
.info("Disconnect-Request with matching Acct-Session-Id")
572 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
573 NAS_IP_Address
="127.0.0.1",
574 NAS_Identifier
="nas.example.com",
576 Event_Timestamp
=int(time
.time()))
577 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectACK
)
579 dev
[0].wait_disconnected(timeout
=10)
580 dev
[0].wait_connected(timeout
=10, error
="Re-connection timed out")
582 logger
.info("Disconnect-Request with matching Acct-Multi-Session-Id")
583 sta
= hapd
.get_sta(addr
)
584 multi_sess_id
= sta
['authMultiSessionId']
585 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
586 NAS_IP_Address
="127.0.0.1",
587 NAS_Identifier
="nas.example.com",
588 Acct_Multi_Session_Id
=multi_sess_id
,
589 Event_Timestamp
=int(time
.time()))
590 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectACK
)
592 dev
[0].wait_disconnected(timeout
=10)
593 dev
[0].wait_connected(timeout
=10, error
="Re-connection timed out")
595 logger
.info("Disconnect-Request with matching User-Name")
596 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
597 NAS_Identifier
="nas.example.com",
598 User_Name
="psk.user@example.com",
599 Event_Timestamp
=int(time
.time()))
600 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectACK
)
602 dev
[0].wait_disconnected(timeout
=10)
603 dev
[0].wait_connected(timeout
=10, error
="Re-connection timed out")
605 logger
.info("Disconnect-Request with matching Calling-Station-Id")
606 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
607 NAS_IP_Address
="127.0.0.1",
608 Calling_Station_Id
=addr
,
609 Event_Timestamp
=int(time
.time()))
610 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectACK
)
612 dev
[0].wait_disconnected(timeout
=10)
613 ev
= dev
[0].wait_event(["CTRL-EVENT-EAP-STARTED", "CTRL-EVENT-CONNECTED"])
615 raise Exception("Timeout while waiting for re-connection")
616 if "CTRL-EVENT-EAP-STARTED" not in ev
:
617 raise Exception("Unexpected skipping of EAP authentication in reconnection")
618 dev
[0].wait_connected(timeout
=10, error
="Re-connection timed out")
620 logger
.info("Disconnect-Request with matching Calling-Station-Id and non-matching CUI")
621 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
622 Calling_Station_Id
=addr
,
623 Chargeable_User_Identity
="foo@example.com",
624 Event_Timestamp
=int(time
.time()))
625 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectNAK
, error_cause
=503)
627 logger
.info("Disconnect-Request with matching CUI")
628 dev
[1].connect("radius-das", key_mgmt
="WPA-EAP",
629 eap
="GPSK", identity
="gpsk-cui",
630 password
="abcdefghijklmnop0123456789abcdef",
632 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
633 Chargeable_User_Identity
="gpsk-chargeable-user-identity",
634 Event_Timestamp
=int(time
.time()))
635 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectACK
)
637 dev
[1].wait_disconnected(timeout
=10)
638 dev
[1].wait_connected(timeout
=10, error
="Re-connection timed out")
640 ev
= dev
[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout
=1)
642 raise Exception("Unexpected disconnection")
644 connect(dev
[2], "radius-das")
646 logger
.info("Disconnect-Request with matching User-Name - multiple sessions matching")
647 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
648 NAS_Identifier
="nas.example.com",
649 User_Name
="psk.user@example.com",
650 Event_Timestamp
=int(time
.time()))
651 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectNAK
, error_cause
=508)
653 logger
.info("Disconnect-Request with User-Name matching multiple sessions, Calling-Station-Id only one")
654 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
655 NAS_Identifier
="nas.example.com",
656 Calling_Station_Id
=addr
,
657 User_Name
="psk.user@example.com",
658 Event_Timestamp
=int(time
.time()))
659 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectACK
)
661 dev
[0].wait_disconnected(timeout
=10)
662 dev
[0].wait_connected(timeout
=10, error
="Re-connection timed out")
664 ev
= dev
[2].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout
=1)
666 raise Exception("Unexpected disconnection")
668 logger
.info("Disconnect-Request with matching Acct-Multi-Session-Id after disassociation")
669 sta
= hapd
.get_sta(addr
)
670 multi_sess_id
= sta
['authMultiSessionId']
671 dev
[0].request("DISCONNECT")
672 dev
[0].wait_disconnected(timeout
=10)
673 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
674 NAS_IP_Address
="127.0.0.1",
675 NAS_Identifier
="nas.example.com",
676 Acct_Multi_Session_Id
=multi_sess_id
,
677 Event_Timestamp
=int(time
.time()))
678 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectACK
)
680 dev
[0].request("RECONNECT")
681 ev
= dev
[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout
=15)
683 raise Exception("Timeout on EAP start")
684 dev
[0].wait_connected(timeout
=15)
686 logger
.info("Disconnect-Request with matching User-Name after disassociation")
687 dev
[0].request("DISCONNECT")
688 dev
[0].wait_disconnected(timeout
=10)
689 dev
[2].request("DISCONNECT")
690 dev
[2].wait_disconnected(timeout
=10)
691 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
692 NAS_IP_Address
="127.0.0.1",
693 NAS_Identifier
="nas.example.com",
694 User_Name
="psk.user@example.com",
695 Event_Timestamp
=int(time
.time()))
696 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectACK
)
698 logger
.info("Disconnect-Request with matching CUI after disassociation")
699 dev
[1].request("DISCONNECT")
700 dev
[1].wait_disconnected(timeout
=10)
701 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
702 NAS_IP_Address
="127.0.0.1",
703 NAS_Identifier
="nas.example.com",
704 Chargeable_User_Identity
="gpsk-chargeable-user-identity",
705 Event_Timestamp
=int(time
.time()))
706 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectACK
)
708 logger
.info("Disconnect-Request with matching Calling-Station-Id after disassociation")
709 dev
[0].request("RECONNECT")
710 ev
= dev
[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout
=15)
712 raise Exception("Timeout on EAP start")
713 dev
[0].wait_connected(timeout
=15)
714 dev
[0].request("DISCONNECT")
715 dev
[0].wait_disconnected(timeout
=10)
716 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
717 NAS_IP_Address
="127.0.0.1",
718 NAS_Identifier
="nas.example.com",
719 Calling_Station_Id
=addr
,
720 Event_Timestamp
=int(time
.time()))
721 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectACK
)
723 logger
.info("Disconnect-Request with mismatching Calling-Station-Id after disassociation")
724 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
725 NAS_IP_Address
="127.0.0.1",
726 NAS_Identifier
="nas.example.com",
727 Calling_Station_Id
=addr
,
728 Event_Timestamp
=int(time
.time()))
729 send_and_check_reply(srv
, req
, pyrad
.packet
.DisconnectNAK
, error_cause
=503)
731 def test_radius_das_coa(dev
, apdev
):
732 """RADIUS Dynamic Authorization Extensions - CoA"""
736 import pyrad
.dictionary
739 raise HwsimSkip("No pyrad modules available")
741 params
= hostapd
.wpa2_eap_params(ssid
="radius-das")
742 params
['radius_das_port'] = "3799"
743 params
['radius_das_client'] = "127.0.0.1 secret"
744 params
['radius_das_require_event_timestamp'] = "1"
745 hapd
= hostapd
.add_ap(apdev
[0], params
)
746 connect(dev
[0], "radius-das")
747 addr
= dev
[0].p2p_interface_addr()
748 sta
= hapd
.get_sta(addr
)
749 id = sta
['dot1xAuthSessionId']
751 dict = pyrad
.dictionary
.Dictionary("dictionary.radius")
753 srv
= pyrad
.client
.Client(server
="127.0.0.1", acctport
=3799,
754 secret
="secret", dict=dict)
758 # hostapd does not currently support CoA-Request, so NAK is expected
759 logger
.info("CoA-Request with matching Acct-Session-Id")
760 req
= radius_das
.CoAPacket(dict=dict, secret
="secret",
762 Event_Timestamp
=int(time
.time()))
763 send_and_check_reply(srv
, req
, pyrad
.packet
.CoANAK
, error_cause
=405)
765 def test_radius_ipv6(dev
, apdev
):
766 """RADIUS connection over IPv6"""
768 params
['ssid'] = 'as'
769 params
['beacon_int'] = '2000'
770 params
['radius_server_clients'] = 'auth_serv/radius_clients_ipv6.conf'
771 params
['radius_server_ipv6'] = '1'
772 params
['radius_server_auth_port'] = '18129'
773 params
['radius_server_acct_port'] = '18139'
774 params
['eap_server'] = '1'
775 params
['eap_user_file'] = 'auth_serv/eap_user.conf'
776 params
['ca_cert'] = 'auth_serv/ca.pem'
777 params
['server_cert'] = 'auth_serv/server.pem'
778 params
['private_key'] = 'auth_serv/server.key'
779 hostapd
.add_ap(apdev
[1], params
)
781 params
= hostapd
.wpa2_eap_params(ssid
="radius-ipv6")
782 params
['auth_server_addr'] = "::0"
783 params
['auth_server_port'] = "18129"
784 params
['acct_server_addr'] = "::0"
785 params
['acct_server_port'] = "18139"
786 params
['acct_server_shared_secret'] = "radius"
787 params
['own_ip_addr'] = "::0"
788 hostapd
.add_ap(apdev
[0], params
)
789 connect(dev
[0], "radius-ipv6")
791 def test_radius_macacl(dev
, apdev
):
793 params
= hostapd
.radius_params()
794 params
["ssid"] = "radius"
795 params
["macaddr_acl"] = "2"
796 hostapd
.add_ap(apdev
[0], params
)
797 dev
[0].connect("radius", key_mgmt
="NONE", scan_freq
="2412")
799 def test_radius_macacl_acct(dev
, apdev
):
800 """RADIUS MAC ACL and accounting enabled"""
801 params
= hostapd
.radius_params()
802 params
["ssid"] = "radius"
803 params
["macaddr_acl"] = "2"
804 params
['acct_server_addr'] = "127.0.0.1"
805 params
['acct_server_port'] = "1813"
806 params
['acct_server_shared_secret'] = "radius"
807 hostapd
.add_ap(apdev
[0], params
)
808 dev
[0].connect("radius", key_mgmt
="NONE", scan_freq
="2412")
809 dev
[1].connect("radius", key_mgmt
="NONE", scan_freq
="2412")
810 dev
[1].request("DISCONNECT")
811 dev
[1].wait_disconnected()
812 dev
[1].request("RECONNECT")
814 def test_radius_failover(dev
, apdev
):
815 """RADIUS Authentication and Accounting server failover"""
816 subprocess
.call(['ip', 'ro', 'replace', '192.168.213.17', 'dev', 'lo'])
817 as_hapd
= hostapd
.Hostapd("as")
818 as_mib_start
= as_hapd
.get_mib(param
="radius_server")
819 params
= hostapd
.wpa2_eap_params(ssid
="radius-failover")
820 params
["auth_server_addr"] = "192.168.213.17"
821 params
["auth_server_port"] = "1812"
822 params
["auth_server_shared_secret"] = "testing"
823 params
['acct_server_addr'] = "192.168.213.17"
824 params
['acct_server_port'] = "1813"
825 params
['acct_server_shared_secret'] = "testing"
826 params
['radius_retry_primary_interval'] = "20"
827 hapd
= hostapd
.add_ap(apdev
[0], params
, no_enable
=True)
828 hapd
.set("auth_server_addr", "127.0.0.1")
829 hapd
.set("auth_server_port", "1812")
830 hapd
.set("auth_server_shared_secret", "radius")
831 hapd
.set('acct_server_addr', "127.0.0.1")
832 hapd
.set('acct_server_port', "1813")
833 hapd
.set('acct_server_shared_secret', "radius")
835 ev
= hapd
.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout
=30)
837 raise Exception("AP startup timed out")
838 if "AP-ENABLED" not in ev
:
839 raise Exception("AP startup failed")
840 start
= os
.times()[4]
843 subprocess
.call(['ip', 'ro', 'replace', 'prohibit', '192.168.213.17'])
844 dev
[0].request("SET EAPOL::authPeriod 5")
845 connect(dev
[0], "radius-failover", wait_connect
=False)
846 dev
[0].wait_connected(timeout
=20)
848 dev
[0].request("SET EAPOL::authPeriod 30")
849 subprocess
.call(['ip', 'ro', 'del', '192.168.213.17'])
851 as_mib_end
= as_hapd
.get_mib(param
="radius_server")
852 req_s
= int(as_mib_start
['radiusAccServTotalRequests'])
853 req_e
= int(as_mib_end
['radiusAccServTotalRequests'])
855 raise Exception("Unexpected RADIUS server acct MIB value")
859 subprocess
.call(['ip', 'ro', 'replace', 'prohibit', '192.168.213.17'])
860 dev
[1].request("SET EAPOL::authPeriod 5")
862 time
.sleep(21 - (end
- start
))
863 connect(dev
[1], "radius-failover", wait_connect
=False)
864 dev
[1].wait_connected(timeout
=20)
866 dev
[1].request("SET EAPOL::authPeriod 30")
867 subprocess
.call(['ip', 'ro', 'del', '192.168.213.17'])
869 def run_pyrad_server(srv
, t_events
):
870 srv
.RunWithStop(t_events
)
872 def test_radius_protocol(dev
, apdev
):
873 """RADIUS Authentication protocol tests with a fake server"""
877 import pyrad
.dictionary
879 raise HwsimSkip("No pyrad modules available")
881 class TestServer(pyrad
.server
.Server
):
882 def _HandleAuthPacket(self
, pkt
):
883 pyrad
.server
.Server
._HandleAuthPacket
(self
, pkt
)
884 logger
.info("Received authentication request")
885 reply
= self
.CreateReplyPacket(pkt
)
886 reply
.code
= pyrad
.packet
.AccessAccept
887 if self
.t_events
['msg_auth'].is_set():
888 logger
.info("Add Message-Authenticator")
889 if self
.t_events
['wrong_secret'].is_set():
890 logger
.info("Use incorrect RADIUS shared secret")
894 hmac_obj
= hmac
.new(pw
)
895 hmac_obj
.update(struct
.pack("B", reply
.code
))
896 hmac_obj
.update(struct
.pack("B", reply
.id))
899 reply
.AddAttribute("Message-Authenticator",
900 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
901 attrs
= reply
._PktEncodeAttributes
()
904 flen
= 4 + 16 + len(attrs
)
905 hmac_obj
.update(struct
.pack(">H", flen
))
906 hmac_obj
.update(pkt
.authenticator
)
907 hmac_obj
.update(attrs
)
908 if self
.t_events
['double_msg_auth'].is_set():
909 logger
.info("Include two Message-Authenticator attributes")
912 reply
.AddAttribute("Message-Authenticator", hmac_obj
.digest())
913 self
.SendReplyPacket(pkt
.fd
, reply
)
915 def RunWithStop(self
, t_events
):
916 self
._poll
= select
.poll()
918 self
._PrepareSockets
()
919 self
.t_events
= t_events
921 while not t_events
['stop'].is_set():
922 for (fd
, event
) in self
._poll
.poll(1000):
923 if event
== select
.POLLIN
:
925 fdo
= self
._fdmap
[fd
]
926 self
._ProcessInput
(fdo
)
927 except ServerPacketError
as err
:
928 logger
.info("pyrad server dropping packet: " + str(err
))
929 except pyrad
.packet
.PacketError
as err
:
930 logger
.info("pyrad server received invalid packet: " + str(err
))
932 logger
.error("Unexpected event in pyrad server main loop")
934 srv
= TestServer(dict=pyrad
.dictionary
.Dictionary("dictionary.radius"),
935 authport
=18138, acctport
=18139)
936 srv
.hosts
["127.0.0.1"] = pyrad
.server
.RemoteHost("127.0.0.1",
939 srv
.BindToAddress("")
941 t_events
['stop'] = threading
.Event()
942 t_events
['msg_auth'] = threading
.Event()
943 t_events
['wrong_secret'] = threading
.Event()
944 t_events
['double_msg_auth'] = threading
.Event()
945 t
= threading
.Thread(target
=run_pyrad_server
, args
=(srv
, t_events
))
949 params
= hostapd
.wpa2_eap_params(ssid
="radius-test")
950 params
['auth_server_port'] = "18138"
951 hapd
= hostapd
.add_ap(apdev
[0], params
)
952 connect(dev
[0], "radius-test", wait_connect
=False)
953 ev
= dev
[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout
=15)
955 raise Exception("Timeout on EAP start")
957 dev
[0].request("REMOVE_NETWORK all")
959 dev
[0].dump_monitor()
960 t_events
['msg_auth'].set()
961 t_events
['wrong_secret'].set()
962 connect(dev
[0], "radius-test", wait_connect
=False)
964 dev
[0].request("REMOVE_NETWORK all")
966 dev
[0].dump_monitor()
967 t_events
['wrong_secret'].clear()
968 connect(dev
[0], "radius-test", wait_connect
=False)
970 dev
[0].request("REMOVE_NETWORK all")
972 dev
[0].dump_monitor()
973 t_events
['double_msg_auth'].set()
974 connect(dev
[0], "radius-test", wait_connect
=False)
977 t_events
['stop'].set()
980 def test_radius_psk(dev
, apdev
):
981 """WPA2 with PSK from RADIUS"""
985 import pyrad
.dictionary
987 raise HwsimSkip("No pyrad modules available")
989 class TestServer(pyrad
.server
.Server
):
990 def _HandleAuthPacket(self
, pkt
):
991 pyrad
.server
.Server
._HandleAuthPacket
(self
, pkt
)
992 logger
.info("Received authentication request")
993 reply
= self
.CreateReplyPacket(pkt
)
994 reply
.code
= pyrad
.packet
.AccessAccept
996 secret
= reply
.secret
997 if self
.t_events
['long'].is_set():
998 p
= b
'\x10' + "0123456789abcdef" + 15 * b
'\x00'
999 b
= hashlib
.md5(secret
+ pkt
.authenticator
+ a
).digest()
1000 pp
= bytearray(p
[0:16])
1002 cc
= bytearray(pp
[i
] ^ bb
[i
] for i
in range(len(bb
)))
1004 b
= hashlib
.md5(reply
.secret
+ bytes(cc
)).digest()
1005 pp
= bytearray(p
[16:32])
1007 cc
+= bytearray(pp
[i
] ^ bb
[i
] for i
in range(len(bb
)))
1009 data
= '\x00' + a
+ bytes(cc
)
1011 p
= b
'\x08' + "12345678" + 7 * b
'\x00'
1012 b
= hashlib
.md5(secret
+ pkt
.authenticator
+ a
).digest()
1015 cc
= bytearray(pp
[i
] ^ bb
[i
] for i
in range(len(bb
)))
1016 data
= '\x00' + a
+ bytes(cc
)
1017 reply
.AddAttribute("Tunnel-Password", data
)
1018 self
.SendReplyPacket(pkt
.fd
, reply
)
1020 def RunWithStop(self
, t_events
):
1021 self
._poll
= select
.poll()
1023 self
._PrepareSockets
()
1024 self
.t_events
= t_events
1026 while not t_events
['stop'].is_set():
1027 for (fd
, event
) in self
._poll
.poll(1000):
1028 if event
== select
.POLLIN
:
1030 fdo
= self
._fdmap
[fd
]
1031 self
._ProcessInput
(fdo
)
1032 except ServerPacketError
as err
:
1033 logger
.info("pyrad server dropping packet: " + str(err
))
1034 except pyrad
.packet
.PacketError
as err
:
1035 logger
.info("pyrad server received invalid packet: " + str(err
))
1037 logger
.error("Unexpected event in pyrad server main loop")
1039 srv
= TestServer(dict=pyrad
.dictionary
.Dictionary("dictionary.radius"),
1040 authport
=18138, acctport
=18139)
1041 srv
.hosts
["127.0.0.1"] = pyrad
.server
.RemoteHost("127.0.0.1",
1044 srv
.BindToAddress("")
1046 t_events
['stop'] = threading
.Event()
1047 t_events
['long'] = threading
.Event()
1048 t
= threading
.Thread(target
=run_pyrad_server
, args
=(srv
, t_events
))
1052 ssid
= "test-wpa2-psk"
1053 params
= hostapd
.radius_params()
1054 params
['ssid'] = ssid
1056 params
["wpa_key_mgmt"] = "WPA-PSK"
1057 params
["rsn_pairwise"] = "CCMP"
1058 params
['macaddr_acl'] = '2'
1059 params
['wpa_psk_radius'] = '2'
1060 params
['auth_server_port'] = "18138"
1061 hapd
= hostapd
.add_ap(apdev
[0], params
)
1062 dev
[0].connect(ssid
, psk
="12345678", scan_freq
="2412")
1063 t_events
['long'].set()
1064 dev
[1].connect(ssid
, psk
="0123456789abcdef", scan_freq
="2412")
1066 t_events
['stop'].set()
1069 def test_radius_auth_force_client_addr(dev
, apdev
):
1070 """RADIUS client address specified"""
1071 params
= hostapd
.wpa2_eap_params(ssid
="radius-auth")
1072 params
['radius_client_addr'] = "127.0.0.1"
1073 hapd
= hostapd
.add_ap(apdev
[0], params
)
1074 connect(dev
[0], "radius-auth")
1076 def test_radius_auth_force_invalid_client_addr(dev
, apdev
):
1077 """RADIUS client address specified and invalid address"""
1078 params
= hostapd
.wpa2_eap_params(ssid
="radius-auth")
1079 #params['radius_client_addr'] = "10.11.12.14"
1080 params
['radius_client_addr'] = "1::2"
1081 hapd
= hostapd
.add_ap(apdev
[0], params
)
1082 connect(dev
[0], "radius-auth", wait_connect
=False)
1083 ev
= dev
[0].wait_event(["CTRL-EVENT-EAP-STARTED"])
1085 raise Exception("Timeout on EAP start")
1086 ev
= dev
[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout
=1)
1088 raise Exception("Unexpected connection")
1090 def add_message_auth(req
):
1091 req
.authenticator
= req
.CreateAuthenticator()
1092 hmac_obj
= hmac
.new(req
.secret
)
1093 hmac_obj
.update(struct
.pack("B", req
.code
))
1094 hmac_obj
.update(struct
.pack("B", req
.id))
1096 # request attributes
1097 req
.AddAttribute("Message-Authenticator",
1098 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
1099 attrs
= req
._PktEncodeAttributes
()
1102 flen
= 4 + 16 + len(attrs
)
1103 hmac_obj
.update(struct
.pack(">H", flen
))
1104 hmac_obj
.update(req
.authenticator
)
1105 hmac_obj
.update(attrs
)
1107 req
.AddAttribute("Message-Authenticator", hmac_obj
.digest())
1109 def test_radius_server_failures(dev
, apdev
):
1110 """RADIUS server failure cases"""
1114 import pyrad
.dictionary
1116 raise HwsimSkip("No pyrad modules available")
1118 dict = pyrad
.dictionary
.Dictionary("dictionary.radius")
1119 client
= pyrad
.client
.Client(server
="127.0.0.1", authport
=1812,
1120 secret
="radius", dict=dict)
1125 req
= client
.CreateAuthPacket(code
=pyrad
.packet
.AccessRequest
,
1127 req
['State'] = 'foo-state'
1128 add_message_auth(req
)
1129 reply
= client
.SendPacket(req
)
1130 if reply
.code
!= pyrad
.packet
.AccessReject
:
1131 raise Exception("Unexpected RADIUS response code " + str(reply
.code
))
1134 req
= client
.CreateAuthPacket(code
=pyrad
.packet
.AccessRequest
,
1136 add_message_auth(req
)
1138 reply
= client
.SendPacket(req
)
1139 raise Exception("Unexpected response")
1140 except pyrad
.client
.Timeout
:
1143 def test_ap_vlan_wpa2_psk_radius_required(dev
, apdev
):
1144 """AP VLAN with WPA2-PSK and RADIUS attributes required"""
1148 import pyrad
.dictionary
1150 raise HwsimSkip("No pyrad modules available")
1152 class TestServer(pyrad
.server
.Server
):
1153 def _HandleAuthPacket(self
, pkt
):
1154 pyrad
.server
.Server
._HandleAuthPacket
(self
, pkt
)
1155 logger
.info("Received authentication request")
1156 reply
= self
.CreateReplyPacket(pkt
)
1157 reply
.code
= pyrad
.packet
.AccessAccept
1158 secret
= reply
.secret
1159 if self
.t_events
['extra'].is_set():
1160 reply
.AddAttribute("Chargeable-User-Identity", "test-cui")
1161 reply
.AddAttribute("User-Name", "test-user")
1162 if self
.t_events
['long'].is_set():
1163 reply
.AddAttribute("Tunnel-Type", 13)
1164 reply
.AddAttribute("Tunnel-Medium-Type", 6)
1165 reply
.AddAttribute("Tunnel-Private-Group-ID", "1")
1166 self
.SendReplyPacket(pkt
.fd
, reply
)
1168 def RunWithStop(self
, t_events
):
1169 self
._poll
= select
.poll()
1171 self
._PrepareSockets
()
1172 self
.t_events
= t_events
1174 while not t_events
['stop'].is_set():
1175 for (fd
, event
) in self
._poll
.poll(1000):
1176 if event
== select
.POLLIN
:
1178 fdo
= self
._fdmap
[fd
]
1179 self
._ProcessInput
(fdo
)
1180 except ServerPacketError
as err
:
1181 logger
.info("pyrad server dropping packet: " + str(err
))
1182 except pyrad
.packet
.PacketError
as err
:
1183 logger
.info("pyrad server received invalid packet: " + str(err
))
1185 logger
.error("Unexpected event in pyrad server main loop")
1187 srv
= TestServer(dict=pyrad
.dictionary
.Dictionary("dictionary.radius"),
1188 authport
=18138, acctport
=18139)
1189 srv
.hosts
["127.0.0.1"] = pyrad
.server
.RemoteHost("127.0.0.1",
1192 srv
.BindToAddress("")
1194 t_events
['stop'] = threading
.Event()
1195 t_events
['long'] = threading
.Event()
1196 t_events
['extra'] = threading
.Event()
1197 t
= threading
.Thread(target
=run_pyrad_server
, args
=(srv
, t_events
))
1201 ssid
= "test-wpa2-psk"
1202 params
= hostapd
.radius_params()
1203 params
['ssid'] = ssid
1205 params
["wpa_key_mgmt"] = "WPA-PSK"
1206 params
["rsn_pairwise"] = "CCMP"
1207 params
['macaddr_acl'] = '2'
1208 params
['dynamic_vlan'] = "2"
1209 params
['wpa_passphrase'] = '0123456789abcdefghi'
1210 params
['auth_server_port'] = "18138"
1211 hapd
= hostapd
.add_ap(apdev
[0], params
)
1213 logger
.info("connecting without VLAN")
1214 dev
[0].connect(ssid
, psk
="0123456789abcdefghi", scan_freq
="2412",
1216 ev
= dev
[0].wait_event(["CTRL-EVENT-CONNECTED",
1217 "CTRL-EVENT-SSID-TEMP-DISABLED"], timeout
=20)
1219 raise Exception("Timeout on connection attempt")
1220 if "CTRL-EVENT-CONNECTED" in ev
:
1221 raise Exception("Unexpected success without vlan parameters")
1222 logger
.info("connecting without VLAN failed as expected")
1224 logger
.info("connecting without VLAN (CUI/User-Name)")
1225 t_events
['extra'].set()
1226 dev
[1].connect(ssid
, psk
="0123456789abcdefghi", scan_freq
="2412",
1228 ev
= dev
[1].wait_event(["CTRL-EVENT-CONNECTED",
1229 "CTRL-EVENT-SSID-TEMP-DISABLED"], timeout
=20)
1231 raise Exception("Timeout on connection attempt")
1232 if "CTRL-EVENT-CONNECTED" in ev
:
1233 raise Exception("Unexpected success without vlan parameters(2)")
1234 logger
.info("connecting without VLAN failed as expected(2)")
1235 t_events
['extra'].clear()
1237 t_events
['long'].set()
1238 logger
.info("connecting with VLAN")
1239 dev
[2].connect(ssid
, psk
="0123456789abcdefghi", scan_freq
="2412",
1241 ev
= dev
[2].wait_event(["CTRL-EVENT-CONNECTED",
1242 "CTRL-EVENT-SSID-TEMP-DISABLED"], timeout
=20)
1244 raise Exception("Timeout on connection attempt")
1245 if "CTRL-EVENT-SSID-TEMP-DISABLED" in ev
:
1246 raise Exception("Unexpected failure with vlan parameters")
1247 logger
.info("connecting with VLAN succeeded as expected")
1249 t_events
['stop'].set()