In the previous RADIUS client implementation, when there are multiple
RADIUS servers, we kept trying the next server when the current message
can not be acked. It leads to endless retry when all the RADIUS servers
are down.
Fix this by keeping a counter for the accumulated retransmit attempts
for the message, and guarantee that after all the servers failover
RADIUS_CLIENT_MAX_FAILOVER times the message will be dropped.
Another issue with the previous code was that the decision regarding
whether the server should fail over was made immediately after we send
out the message. This patch guarantees we consider whether a server
needs failover after pending ack times out.
Signed-off-by: Bo Chen<bochen@meraki.com>
Reword the comments to make gcc 8.1 recognize these as designed cases
and not trigger implicit-fallthrough warnings.
Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
When the RADIUS client has not yet been fully enabled, MIB command was
segfaulting hostapd.
Signed-off-by: Eduardo Abinader <eduardoabinader@gmail.com>
This tells to the server how long we have been trying to transmit the
message so that the actual time of the message generation can be
determined from receive time (ignoring network delays and only at
accuracy of one second).
For interim updates, only value 0 is used since there are no
retransmissions of the same message. For other accounting messages, the
initial attempt goes out with value 0 and the retransmissions, if
needed, show the number of seconds the message has been waiting in the
queue.
Update the Identifier and Authenticator in the messages whenever
updating the Acct-Delay-Time per RFC 2866, 4.1 requirements.
Signed-off-by: Jouni Malinen <j@w1.fi>
Instead of using the RADIUS client retransmission design with the old
RADIUS message contents for each retry, trigger a completely new interim
accounting update instance more quickly (using the same schedule as
RADIUS message retransmissions) to improve accounting updates in cases
where RADIUS message delivery fails. This allows the server to get up to
date information from the time the "retry" message was sent instead of
the old information from the time the first failed attempt was sent.
Signed-off-by: Jouni Malinen <j@w1.fi>
This allows RADIUS failover to be performed if send() return EACCES
error which is what happens after a recent Linux kernel commit
0315e382704817b279e5693dca8ab9d89aa20b3f ('net: Fix behaviour of
unreachable, blackhole and prohibit') for a local sender when route type
is prohibit.
This fixes the hwsim test case radius_failover when running against a
kernel build that includes that commit.
Signed-off-by: Jouni Malinen <j@w1.fi>
On RADIUS auth/acct failures hostapd will try a new server if one is
available. Reuse the failover logic to force a socket renewal if only
one RADIUS server is configured.
This fixes problems when a route for the RADIUS server gets added after
the socket was "connected". The RADIUS socket is still sending the
RADIUS requests out using the previous route.
Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
If a connection with the primary server cannot be established, restore
connection to the previously used server.
Signed-off-by: Jouni Malinen <j@w1.fi>
Commit 347c55e216 ('RADIUS client: Re-try
connection if socket is closed on retransmit') added a new option for
initialing RADIUS server failover from radius_client_retransmit(), but
ended up trying to change authentication servers when accounting server
was supposed to be changed due to a copy-paste issue.
Signed-off-by: Jouni Malinen <j@w1.fi>
Commit 347c55e216 ('RADIUS client: Re-try
connection if socket is closed on retransmit') added a possibility of
executing RADIUS server failover change within
radius_client_retransmit() without taking into account that this
operation may end up freeing the pending message that is being
processed. This could result in use of freed memory. Avoid this by
checking whether any pending messages have been removed and if so, do
not try to retransmit the potentially freed message.
Signed-off-by: Jouni Malinen <j@w1.fi>
Previously, send() was called with invalid fd = -1 in some error cases
for retransmission and this could even result in a loop of multiple such
attempts. This is obviously not going to work, so drop such attempts and
instead, try to reconnect a socket to the server if the current socket
is not valid.
In addition, initiate server failover immediately if the current socket
is not valid instead of waiting for a timeout.
Signed-off-by: Jouni Malinen <j@w1.fi>
If the initial attempt at opening the socket connection to the RADIUS
server failed due to missing IP connectivity during startup, e.g., with
"connect[radius]: Network is unreachable", hostapd did not try to
reconnect when RADIUS messages were sent. Instead, it only reported "No
authentication server configured" even if the configuration did have a
server entry.
This was broken by commit 9ed4076673
('RADIUS client: Do not try to send message without socket') for the
initial case and the more recent fixes in RADIUS server failover cases
did not cover the initial failure case.
Signed-off-by: Jouni Malinen <j@w1.fi>
It was possible for an out-of-memory code path to trigger NULL pointer
dereference when preparing a RADIUS accounting report.
Signed-off-by: Jouni Malinen <j@w1.fi>
It could have been possible to select a socket that is not open
(sel_sock == -1) and try to use that in socket operations. This would
fail with potentially confusing error messages. Make this clearer by
printing a clear debug log entry on socket not being available.
(CID 72696)
Signed-off-by: Jouni Malinen <j@w1.fi>
In theory, this function could fail, so check the return value before
printing out the RADIUS local address debug message (CID 72700).
Signed-off-by: Jouni Malinen <j@w1.fi>
It is possible for the connect() call to fail (e.g., due to unreachable
network based on local routing table), so the current auth/acct_sock may
be left to -1. Use that as an addition trigger to allow server failover
operation to be performed more quickly if it is known that the
retransmission attempt will not succeed anyway.
Signed-off-by: Jouni Malinen <j@w1.fi>
The re-open socket to the current RADIUS server code path did not work
in the expected way here. The pending authentication messages do not
need to be flushed in that case and neither should the retransmission
parameters be cleared. Fix this by performing these operations only if
the server did actually change as a part of a failover operation.
Signed-off-by: Jouni Malinen <j@w1.fi>
Both IPv4 and IPv6 sockets were not closed consistently in the paths
that tried to change RADIUS servers. This could result in leaking
sockets and leaving behind registered eloop events to freed memory on
interface removal.
Signed-off-by: Jouni Malinen <j@w1.fi>
While iterating through RADIUS messages in radius_client_timer(), one
message entry may get flushed by "radius_client_retransmit -->
radius_client_handle_send_error --> radius_client_init_auth -->
radius_change_server --> radius_client_flush". This could result in
freed memory being accessed afterwards.
Signed-off-by: Jerry Yang <xyang@sonicwall.com>
This is one more possible send() error that should trigger RADIUS server
change if multiple servers are configured.
Signed-off-by: Jouni Malinen <j@w1.fi>
It is possible for the RADIUS authentication/accounting socket to not be
open even if partial RADIUS server configuration has been done through
the control interface SET commands. Previously, this resulted in send()
attempt using fd=-1 which fails with bad file descriptor. Clean this up
by logging this as a missing configuration instead of trying to send the
message when that is known to fail.
Signed-off-by: Jouni Malinen <j@w1.fi>
Since the RADIUS client cares about relative time (retry timeout)
only, it should use monotonic time.
Signed-hostap: Johannes Berg <johannes.berg@intel.com>
ieee802_1x_encapsulate_radius() frees the RADIUS message if
radius_client_send() returns error. This could have resulted in use of
freed memory and double freeing of the RADIUS message if send() fails
since the message is also left in the retransmit list. Avoid this by not
returning error to the caller in such a case.
Signed-off-by: Alexander Couzens <lynxis@c-base.org>
The internal pointer to RADIUS client configuration needs to be
updated whenever a new hostapd configuration is loaded. Without
this, freed memory may be dereferenced and this can result in
segmentation faults.
This is not actually used at all and it looks like the rules for
maintaining the old/new RADIUS configuration are not very clear in the
case the RADIUS client configuration did not change. Consequently, it
is better to just remove this for now and if similar functionality is
ever needed, redesign it to be easier to use without causing hard to
find issues with using freed memory.
Simpler approach to reconfiguring the RADIUS client would involve
just deinitializing the old context unconditionally and initializing
a new one whenever the configuration could have changed.
When Linux has Path MTU discovery enabled, it sets by default the DF bit
on all outgoing datagrams, also UDP ones. If a RADIUS message is bigger
than the smallest MTU size to the target, it will be discarded.
This effectively limits RADIUS messages to ~ 1500 Bytes, while they can
be up to 4k according to RFC2865. In practice, this can mean trouble
when doing EAP-TLS with many RADIUS attributes besides the EAP-Message.
[Bug 326]
Allow the user to set the IP address of the eapol_test client. This if
very useful when you have a machine with many interfaces and want to use a
particular one for testing RADIUS connectivity. For instance when I run the
national eduroam proxy I can only connect to other server from a particular
address, an our machine happens to have several IPs. So if I want to run
connectivity tests, I must make sure that my test uses a particular
interface. The -A option allows one to set this).
(jm: cleaned up to use radius configuration structure instead of global
variable for the address and added IPv6 support)