]>
git.ipfire.org Git - thirdparty/hostap.git/blob - tests/hwsim/test_radius.py
4 # Copyright (c) 2013-2014, Jouni Malinen <j@w1.fi>
6 # This software may be distributed under the terms of the BSD license.
7 # See README for more details.
10 logger
= logging
.getLogger()
15 def connect(dev
, ssid
, wait_connect
=True):
16 dev
.connect(ssid
, key_mgmt
="WPA-EAP", scan_freq
="2412",
17 eap
="PSK", identity
="psk.user@example.com",
18 password_hex
="0123456789abcdef0123456789abcdef",
19 wait_connect
=wait_connect
)
21 def test_radius_auth_unreachable(dev
, apdev
):
22 """RADIUS Authentication server unreachable"""
23 params
= hostapd
.wpa2_eap_params(ssid
="radius-auth")
24 params
['auth_server_port'] = "18139"
25 hostapd
.add_ap(apdev
[0]['ifname'], params
)
26 hapd
= hostapd
.Hostapd(apdev
[0]['ifname'])
27 connect(dev
[0], "radius-auth", wait_connect
=False)
28 ev
= dev
[0].wait_event(["CTRL-EVENT-EAP-STARTED"])
30 raise Exception("Timeout on EAP start")
31 logger
.info("Checking for RADIUS retries")
34 if "radiusAuthClientAccessRequests" not in mib
:
35 raise Exception("Missing MIB fields")
36 if int(mib
["radiusAuthClientAccessRetransmissions"]) < 1:
37 raise Exception("Missing RADIUS Authentication retransmission")
38 if int(mib
["radiusAuthClientPendingRequests"]) < 1:
39 raise Exception("Missing pending RADIUS Authentication request")
41 def test_radius_acct_unreachable(dev
, apdev
):
42 """RADIUS Accounting server unreachable"""
43 params
= hostapd
.wpa2_eap_params(ssid
="radius-acct")
44 params
['acct_server_addr'] = "127.0.0.1"
45 params
['acct_server_port'] = "18139"
46 params
['acct_server_shared_secret'] = "radius"
47 hostapd
.add_ap(apdev
[0]['ifname'], params
)
48 hapd
= hostapd
.Hostapd(apdev
[0]['ifname'])
49 connect(dev
[0], "radius-acct")
50 logger
.info("Checking for RADIUS retries")
53 if "radiusAccClientRetransmissions" not in mib
:
54 raise Exception("Missing MIB fields")
55 if int(mib
["radiusAccClientRetransmissions"]) < 2:
56 raise Exception("Missing RADIUS Accounting retransmissions")
57 if int(mib
["radiusAccClientPendingRequests"]) < 2:
58 raise Exception("Missing pending RADIUS Accounting requests")
60 def test_radius_acct(dev
, apdev
):
61 """RADIUS Accounting"""
62 as_hapd
= hostapd
.Hostapd("as")
63 as_mib_start
= as_hapd
.get_mib(param
="radius_server")
64 params
= hostapd
.wpa2_eap_params(ssid
="radius-acct")
65 params
['acct_server_addr'] = "127.0.0.1"
66 params
['acct_server_port'] = "1813"
67 params
['acct_server_shared_secret'] = "radius"
68 hostapd
.add_ap(apdev
[0]['ifname'], params
)
69 hapd
= hostapd
.Hostapd(apdev
[0]['ifname'])
70 connect(dev
[0], "radius-acct")
71 logger
.info("Checking for RADIUS counters")
75 if int(mib
['radiusAccClientResponses']) >= 2:
80 raise Exception("Did not receive Accounting-Response packets")
82 if int(mib
['radiusAccClientRetransmissions']) > 0:
83 raise Exception("Unexpected Accounting-Request retransmission")
85 as_mib_end
= as_hapd
.get_mib(param
="radius_server")
87 req_s
= int(as_mib_start
['radiusAccServTotalRequests'])
88 req_e
= int(as_mib_end
['radiusAccServTotalRequests'])
90 raise Exception("Unexpected RADIUS server acct MIB value")
92 acc_s
= int(as_mib_start
['radiusAuthServAccessAccepts'])
93 acc_e
= int(as_mib_end
['radiusAuthServAccessAccepts'])
95 raise Exception("Unexpected RADIUS server auth MIB value")
97 def test_radius_das_disconnect(dev
, apdev
):
98 """RADIUS Dynamic Authorization Extensions - Disconnect"""
102 import pyrad
.dictionary
107 params
= hostapd
.wpa2_eap_params(ssid
="radius-das")
108 params
['radius_das_port'] = "3799"
109 params
['radius_das_client'] = "127.0.0.1 secret"
110 params
['radius_das_require_event_timestamp'] = "1"
111 hapd
= hostapd
.add_ap(apdev
[0]['ifname'], params
)
112 connect(dev
[0], "radius-das")
113 addr
= dev
[0].p2p_interface_addr()
114 sta
= hapd
.get_sta(addr
)
115 id = sta
['dot1xAuthSessionId']
117 dict = pyrad
.dictionary
.Dictionary("dictionary.radius")
119 srv
= pyrad
.client
.Client(server
="127.0.0.1", acctport
=3799,
120 secret
="secret", dict=dict)
124 logger
.info("Disconnect-Request with incorrect secret")
125 req
= radius_das
.DisconnectPacket(dict=dict, secret
="incorrect",
127 NAS_Identifier
="localhost",
128 Event_Timestamp
=int(time
.time()))
131 reply
= srv
.SendPacket(req
)
132 raise Exception("Unexpected response to Disconnect-Request")
133 except pyrad
.client
.Timeout
:
134 logger
.info("Disconnect-Request with incorrect secret properly ignored")
136 logger
.info("Disconnect-Request without Event-Timestamp")
137 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
138 User_Name
="psk.user@example.com")
141 reply
= srv
.SendPacket(req
)
142 raise Exception("Unexpected response to Disconnect-Request")
143 except pyrad
.client
.Timeout
:
144 logger
.info("Disconnect-Request without Event-Timestamp properly ignored")
146 logger
.info("Disconnect-Request with non-matching Event-Timestamp")
147 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
148 User_Name
="psk.user@example.com",
149 Event_Timestamp
=123456789)
152 reply
= srv
.SendPacket(req
)
153 raise Exception("Unexpected response to Disconnect-Request")
154 except pyrad
.client
.Timeout
:
155 logger
.info("Disconnect-Request with non-matching Event-Timestamp properly ignored")
157 logger
.info("Disconnect-Request with unsupported attribute")
158 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
161 Event_Timestamp
=int(time
.time()))
162 reply
= srv
.SendPacket(req
)
163 logger
.debug("RADIUS response from hostapd")
164 for i
in reply
.keys():
165 logger
.debug("%s: %s" % (i
, reply
[i
]))
166 if reply
.code
!= pyrad
.packet
.DisconnectNAK
:
167 raise Exception("Unexpected response code")
168 if 'Error-Cause' not in reply
:
169 raise Exception("Missing Error-Cause")
170 if reply
['Error-Cause'][0] != 401:
171 raise Exception("Unexpected Error-Cause: {}".format(reply
['Error-Cause']))
173 logger
.info("Disconnect-Request with invalid Calling-Station-Id")
174 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
176 Calling_Station_Id
="foo",
177 Event_Timestamp
=int(time
.time()))
178 reply
= srv
.SendPacket(req
)
179 logger
.debug("RADIUS response from hostapd")
180 for i
in reply
.keys():
181 logger
.debug("%s: %s" % (i
, reply
[i
]))
182 if reply
.code
!= pyrad
.packet
.DisconnectNAK
:
183 raise Exception("Unexpected response code")
184 if 'Error-Cause' not in reply
:
185 raise Exception("Missing Error-Cause")
186 if reply
['Error-Cause'][0] != 407:
187 raise Exception("Unexpected Error-Cause: {}".format(reply
['Error-Cause']))
189 logger
.info("Disconnect-Request with mismatching User-Name")
190 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
192 Event_Timestamp
=int(time
.time()))
193 reply
= srv
.SendPacket(req
)
194 logger
.debug("RADIUS response from hostapd")
195 for i
in reply
.keys():
196 logger
.debug("%s: %s" % (i
, reply
[i
]))
197 if reply
.code
!= pyrad
.packet
.DisconnectNAK
:
198 raise Exception("Unexpected response code")
199 if 'Error-Cause' not in reply
:
200 raise Exception("Missing Error-Cause")
201 if reply
['Error-Cause'][0] != 503:
202 raise Exception("Unexpected Error-Cause: {}".format(reply
['Error-Cause']))
204 logger
.info("Disconnect-Request with mismatching Calling-Station-Id")
205 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
206 Calling_Station_Id
="12:34:56:78:90:aa",
207 Event_Timestamp
=int(time
.time()))
208 reply
= srv
.SendPacket(req
)
209 logger
.debug("RADIUS response from hostapd")
210 for i
in reply
.keys():
211 logger
.debug("%s: %s" % (i
, reply
[i
]))
212 if reply
.code
!= pyrad
.packet
.DisconnectNAK
:
213 raise Exception("Unexpected response code")
214 if 'Error-Cause' not in reply
:
215 raise Exception("Missing Error-Cause")
216 if reply
['Error-Cause'][0] != 503:
217 raise Exception("Unexpected Error-Cause: {}".format(reply
['Error-Cause']))
219 logger
.info("Disconnect-Request with mismatching Acct-Session-Id")
220 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
221 Acct_Session_Id
="12345678-87654321",
222 Event_Timestamp
=int(time
.time()))
223 reply
= srv
.SendPacket(req
)
224 logger
.debug("RADIUS response from hostapd")
225 for i
in reply
.keys():
226 logger
.debug("%s: %s" % (i
, reply
[i
]))
227 if reply
.code
!= pyrad
.packet
.DisconnectNAK
:
228 raise Exception("Unexpected response code")
229 if 'Error-Cause' not in reply
:
230 raise Exception("Missing Error-Cause")
231 if reply
['Error-Cause'][0] != 503:
232 raise Exception("Unexpected Error-Cause: {}".format(reply
['Error-Cause']))
234 ev
= dev
[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout
=1)
236 raise Exception("Unexpected disconnection")
238 logger
.info("Disconnect-Request with matching Acct-Session-Id")
239 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
241 Event_Timestamp
=int(time
.time()))
242 reply
= srv
.SendPacket(req
)
243 logger
.debug("RADIUS response from hostapd")
244 for i
in reply
.keys():
245 logger
.debug("%s: %s" % (i
, reply
[i
]))
246 if reply
.code
!= pyrad
.packet
.DisconnectACK
:
247 raise Exception("Unexpected response code")
249 ev
= dev
[0].wait_event(["CTRL-EVENT-DISCONNECTED"])
251 raise Exception("Timeout while waiting for disconnection")
252 ev
= dev
[0].wait_event(["CTRL-EVENT-CONNECTED"])
254 raise Exception("Timeout while waiting for re-connection")
256 logger
.info("Disconnect-Request with matching User-Name")
257 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
258 User_Name
="psk.user@example.com",
259 Event_Timestamp
=int(time
.time()))
260 reply
= srv
.SendPacket(req
)
261 logger
.debug("RADIUS response from hostapd")
262 for i
in reply
.keys():
263 logger
.debug("%s: %s" % (i
, reply
[i
]))
264 if reply
.code
!= pyrad
.packet
.DisconnectACK
:
265 raise Exception("Unexpected response code")
267 ev
= dev
[0].wait_event(["CTRL-EVENT-DISCONNECTED"])
269 raise Exception("Timeout while waiting for disconnection")
270 ev
= dev
[0].wait_event(["CTRL-EVENT-CONNECTED"])
272 raise Exception("Timeout while waiting for re-connection")
274 logger
.info("Disconnect-Request with matching Calling-Station-Id")
275 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
276 Calling_Station_Id
=addr
,
277 Event_Timestamp
=int(time
.time()))
278 reply
= srv
.SendPacket(req
)
279 logger
.debug("RADIUS response from hostapd")
280 for i
in reply
.keys():
281 logger
.debug("%s: %s" % (i
, reply
[i
]))
282 if reply
.code
!= pyrad
.packet
.DisconnectACK
:
283 raise Exception("Unexpected response code")
285 ev
= dev
[0].wait_event(["CTRL-EVENT-DISCONNECTED"])
287 raise Exception("Timeout while waiting for disconnection")
288 ev
= dev
[0].wait_event(["CTRL-EVENT-CONNECTED"])
290 raise Exception("Timeout while waiting for re-connection")
292 logger
.info("Disconnect-Request with matching Calling-Station-Id and non-matching CUI")
293 req
= radius_das
.DisconnectPacket(dict=dict, secret
="secret",
294 Calling_Station_Id
=addr
,
295 Chargeable_User_Identity
="foo@example.com",
296 Event_Timestamp
=int(time
.time()))
297 reply
= srv
.SendPacket(req
)
298 logger
.debug("RADIUS response from hostapd")
299 for i
in reply
.keys():
300 logger
.debug("%s: %s" % (i
, reply
[i
]))
301 if reply
.code
!= pyrad
.packet
.DisconnectACK
:
302 raise Exception("Unexpected response code")
304 ev
= dev
[0].wait_event(["CTRL-EVENT-DISCONNECTED"])
306 raise Exception("Timeout while waiting for disconnection")
307 ev
= dev
[0].wait_event(["CTRL-EVENT-CONNECTED"])
309 raise Exception("Timeout while waiting for re-connection")
311 def test_radius_das_coa(dev
, apdev
):
312 """RADIUS Dynamic Authorization Extensions - CoA"""
316 import pyrad
.dictionary
321 params
= hostapd
.wpa2_eap_params(ssid
="radius-das")
322 params
['radius_das_port'] = "3799"
323 params
['radius_das_client'] = "127.0.0.1 secret"
324 params
['radius_das_require_event_timestamp'] = "1"
325 hapd
= hostapd
.add_ap(apdev
[0]['ifname'], params
)
326 connect(dev
[0], "radius-das")
327 addr
= dev
[0].p2p_interface_addr()
328 sta
= hapd
.get_sta(addr
)
329 id = sta
['dot1xAuthSessionId']
331 dict = pyrad
.dictionary
.Dictionary("dictionary.radius")
333 srv
= pyrad
.client
.Client(server
="127.0.0.1", acctport
=3799,
334 secret
="secret", dict=dict)
338 # hostapd does not currently support CoA-Request, so NAK is expected
339 logger
.info("CoA-Request with matching Acct-Session-Id")
340 req
= radius_das
.CoAPacket(dict=dict, secret
="secret",
342 Event_Timestamp
=int(time
.time()))
343 reply
= srv
.SendPacket(req
)
344 logger
.debug("RADIUS response from hostapd")
345 for i
in reply
.keys():
346 logger
.debug("%s: %s" % (i
, reply
[i
]))
347 if reply
.code
!= pyrad
.packet
.CoANAK
:
348 raise Exception("Unexpected response code")
349 if 'Error-Cause' not in reply
:
350 raise Exception("Missing Error-Cause")
351 if reply
['Error-Cause'][0] != 405:
352 raise Exception("Unexpected Error-Cause: {}".format(reply
['Error-Cause']))