summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRohini Sangam <rsangam@mvista.com>2024-10-15 12:27:59 +0530
committerArmin Kuster <akuster808@gmail.com>2024-12-08 14:39:17 -0500
commit61b0967009b1743637c8f02f21c2e3eef08d648e (patch)
treee2e86a00fa5e23dc727728b3975ca7b3957ef63c
parent82a9ac867d2f661b77435e13842ab42a63a352ac (diff)
downloadmeta-openembedded-61b0967009b1743637c8f02f21c2e3eef08d648e.tar.gz
freeradius: Security fix for CVE-2024-3596
CVE fixed: - CVE-2024-3596 freeradius: forgery attack Upstream-Status: Backport from v3.0.x branch, commit range 3a00a6ecc188629b0441fd45ad61ca8986de156e..da643f1edc267ce95260dc36069e6f1a7a4d66f8 Signed-off-by: Rohini Sangam <rsangam@mvista.com> Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> Signed-off-by: Armin Kuster <akuster808@gmail.com>
-rw-r--r--meta-networking/recipes-connectivity/freeradius/files/CVE-2024-3596.patch1506
-rw-r--r--meta-networking/recipes-connectivity/freeradius/freeradius_3.0.21.bb1
2 files changed, 1507 insertions, 0 deletions
diff --git a/meta-networking/recipes-connectivity/freeradius/files/CVE-2024-3596.patch b/meta-networking/recipes-connectivity/freeradius/files/CVE-2024-3596.patch
new file mode 100644
index 0000000000..1778e8e927
--- /dev/null
+++ b/meta-networking/recipes-connectivity/freeradius/files/CVE-2024-3596.patch
@@ -0,0 +1,1506 @@
1From 441967ba1d1ec28aa9582ab0253ad01e14b42148 Mon Sep 17 00:00:00 2001
2From: Arran Cudbard-Bell <a.cudbardb@freeradius.org>
3Date: Sun, 30 Jun 2024 14:03:17 -0600
4Subject: [PATCH] CVE-2024-3596: Backport fix for BlastRADIUS
5
6Upstream-Status: Backport from v3.0.x branch, commit range 3a00a6ecc188629b0441fd45ad61ca8986de156e..da643f1edc267ce95260dc36069e6f1a7a4d66f8
7CVE: CVE-2024-3596
8
9Signed-off-by: Rohini Sangam <rsangam@mvista.com>
10---
11 man/man1/radclient.1 | 10 ++-
12 man/man1/radtest.1 | 11 ++-
13 raddb/clients.conf | 47 ++++++++--
14 raddb/proxy.conf | 19 +++++
15 raddb/radiusd.conf.in | 185 ++++++++++++++++++++++++++++++++++++++++
16 src/include/clients.h | 6 +-
17 src/include/conffile.h | 1 +
18 src/include/libradius.h | 19 ++++-
19 src/include/radius.h | 1 +
20 src/include/radiusd.h | 6 ++
21 src/include/realms.h | 1 +
22 src/lib/radius.c | 87 +++++++++++++++++--
23 src/main/client.c | 45 ++++++++--
24 src/main/conffile.c | 4 +-
25 src/main/listen.c | 141 +++++++++++++++++++++++++++++-
26 src/main/mainconfig.c | 70 +++++++++++++++
27 src/main/process.c | 65 ++++++++++++++
28 src/main/radclient.c | 147 ++++++++++++++++++++++++++++++-
29 src/main/radtest.in | 6 +-
30 src/main/realms.c | 11 +++
31 src/main/tls_listen.c | 5 ++
32 21 files changed, 855 insertions(+), 32 deletions(-)
33
34diff --git a/man/man1/radclient.1 b/man/man1/radclient.1
35index 229dcae0c7..b83bee931a 100644
36--- a/man/man1/radclient.1
37+++ b/man/man1/radclient.1
38@@ -1,10 +1,11 @@
39-.TH RADCLIENT 1 "22 March 2019" "" "FreeRADIUS Daemon"
40+.TH RADCLIENT 1 "21 May 2024" "" "FreeRADIUS Daemon"
41 .SH NAME
42 radclient - send packets to a RADIUS server, show reply
43 .SH SYNOPSIS
44 .B radclient
45 .RB [ \-4 ]
46 .RB [ \-6 ]
47+.RB [ \-b ]
48 .RB [ \-c
49 .IR count ]
50 .RB [ \-d
51@@ -52,6 +53,13 @@ automatically encrypted before the packet is sent to the server.
52 Use IPv4 (default)
53 .IP \-6
54 Use IPv6
55+.IP \-b
56+Enforce the Blast RADIUS checks. All replies to an Access-Request packet
57+must contain a Message-Authenticator as the first attribute.
58+
59+For compatibility with old servers, this flag is not set by default.
60+However, radclient still checks for the Blast RADIUS signature, and
61+discards packets which match the attack.
62 .IP \-c\ \fIcount\fP
63 Send each packet \fIcount\fP times.
64 .IP \-d\ \fIraddb_directory\fP
65diff --git a/man/man1/radtest.1 b/man/man1/radtest.1
66index b3184779c0..6bfab75944 100644
67--- a/man/man1/radtest.1
68+++ b/man/man1/radtest.1
69@@ -1,4 +1,4 @@
70-.TH RADTEST 1 "5 April 2010" "" "FreeRADIUS Daemon"
71+.TH RADTEST 1 "21 May 2024" "" "FreeRADIUS Daemon"
72 .SH NAME
73 radtest - send packets to a RADIUS server, show reply
74 .SH SYNOPSIS
75@@ -15,6 +15,8 @@ radtest - send packets to a RADIUS server, show reply
76 .IR ]
77 .RB [ \-6
78 .IR ]
79+.RB [ \-b
80+.IR
81 .I user password radius-server nas-port-number secret
82 .RB [ ppphint ]
83 .RB [ nasname ]
84@@ -26,6 +28,13 @@ way to test a radius server.
85
86 .SH OPTIONS
87
88+.IP \-b
89+Enforce the Blast RADIUS checks. All replies to an Access-Request packet
90+must contain a Message-Authenticator as the first attribute.
91+
92+For compatibility with old servers, this flag is not set by default.
93+However, radclient still checks for the Blast RADIUS signature, and
94+discards packets which match the attack.
95 .IP "\-d \fIraddb_directory\fP"
96 The directory that contains the RADIUS dictionary files. Defaults to
97 \fI/etc/raddb\fP.
98diff --git a/raddb/clients.conf b/raddb/clients.conf
99index 76b300d3c5..d55414b7d2 100644
100--- a/raddb/clients.conf
101+++ b/raddb/clients.conf
102@@ -100,15 +100,44 @@ client localhost {
103 secret = testing123
104
105 #
106- # Old-style clients do not send a Message-Authenticator
107- # in an Access-Request. RFC 5080 suggests that all clients
108- # SHOULD include it in an Access-Request. The configuration
109- # item below allows the server to require it. If a client
110- # is required to include a Message-Authenticator and it does
111- # not, then the packet will be silently discarded.
112- #
113- # allowed values: yes, no
114- require_message_authenticator = no
115+ # The global configuration "security.require_message_authenticator"
116+ # flag sets the default for all clients. That default can be
117+ # over-ridden here, by setting it to a value. If no value is set,
118+ # then the default from the "radiusd.conf" file is used.
119+ #
120+ # See that file for full documentation on the flag, along
121+ # with allowed values and meanings.
122+ #
123+ # This flag exists solely for legacy clients which do not send
124+ # Message-Authenticator in all Access-Request packets. We do not
125+ # recommend setting it to "no".
126+ #
127+ # The number one way to protect yourself from the BlastRADIUS
128+ # attack is to update all RADIUS servers, and then set this
129+ # flag to "yes". If all RADIUS servers are updated, and if
130+ # all of them have this flag set to "yes" for all clients,
131+ # then your network is safe. You can then upgrade the
132+ # clients when it is convenient, instead of rushing the
133+ # upgrades.
134+ #
135+ # allowed values: yes, no, auto
136+# require_message_authenticator = no
137+
138+ #
139+ # The global configuration "security.limit_proxy_state"
140+ # flag sets the default for all clients. That default can be
141+ # over-ridden here, by setting it to "no".
142+ #
143+ # See that file for full documentation on the flag, along
144+ # with allowed values,and meanings.
145+ #
146+ # This flag exists solely for legacy clients which do not send
147+ # Message-Authenticator in all Access-Request packets. We do not
148+ # recommend setting it to "no".
149+ #
150+ # allowed values: yes, no, auto
151+ #
152+# limit_proxy_state = yes
153
154 #
155 # The short name is used as an alias for the fully qualified
156diff --git a/raddb/proxy.conf b/raddb/proxy.conf
157index 91b4b37930..fa362b8a74 100644
158--- a/raddb/proxy.conf
159+++ b/raddb/proxy.conf
160@@ -204,6 +204,25 @@ home_server localhost {
161 #
162 secret = testing123
163
164+
165+ #
166+ # The global configuration "security.require_message_authenticator"
167+ # flag sets the default for all home servers. That default can be
168+ # over-ridden here, by setting it to a value. If no value is set,
169+ # then the default from the "radiusd.conf" file is used.
170+ #
171+ # See that file for full documentation on the flag, along
172+ # with allowed values and meanings.
173+ #
174+ # This flag exists solely for legacy home servers which do
175+ # not send Message-Authenticator in all Access-Accept,
176+ # Access-Reject, or Access-Challenge packets. We do not
177+ # recommend setting it to "no".
178+ #
179+ # allowed values: yes, no, auto
180+ #
181+# require_message_authenticator = no
182+
183 ############################################################
184 #
185 # The rest of the configuration items listed here are optional,
186diff --git a/raddb/radiusd.conf.in b/raddb/radiusd.conf.in
187index e8aee3c001..5b8800bfc8 100644
188--- a/raddb/radiusd.conf.in
189+++ b/raddb/radiusd.conf.in
190@@ -564,6 +564,191 @@ security {
191 #
192 status_server = yes
193
194+ #
195+ # Global configuration for requiring Message-Authenticator in
196+ # all Access-* packets sent over UDP or TCP. This flag is
197+ # ignored for TLS.
198+ #
199+ # The number one way to protect yourself from the BlastRADIUS
200+ # attack is to update all RADIUS servers, and then set this
201+ # flag to "yes". If all RADIUS servers are updated, and if
202+ # all of them have this flag set to "yes" for all clients,
203+ # then your network is safe. You can then upgrade the
204+ # clients when it is convenient, instead of rushing the
205+ # upgrades.
206+ #
207+ # This flag sets the global default for all clients and home
208+ # servers. It can be over-ridden in an individual client or
209+ # home_server definition by adding the same flag to that
210+ # section with an appropriate value.
211+ #
212+ # All upgraded RADIUS implementations should send
213+ # Message-Authenticator in all Access-Request, Access-Accept,
214+ # Access-Reject, and Access-Challenge packets. Once all
215+ # systems are upgraded, setting this flag to "yes" is the
216+ # best protection from the attack.
217+ #
218+ # The possible values and meanings for
219+ # "require_message_authenticator" are;
220+ #
221+ # * "no" - allow Access-* packet which do not contain
222+ # Message-Authenticator
223+ #
224+ # For a client, if this flag is set to "no", then the
225+ # "limit_proxy_state" flag, below, is also checked.
226+ #
227+ # For a home_server, if this flag is set to "no", then the
228+ # Access-Accept, Access-Reject, and Access-Challenge
229+ # packets do not need to contain Message-Authenticator.
230+ #
231+ # The only reason to set this flag to "no" is when the
232+ # RADIUS client or home server has not been updated. It is
233+ # always safer to set this flag "no" in the individual
234+ # client or home_server definition. The global flag SHOULD
235+ # still be set to a safe value: "yes".
236+ #
237+ # WARNING: Setting this flag and the "limit_proxy_state"
238+ # flag to "no" will allow MITM attackers to create fake
239+ # Access-Accept packets to the NAS! At least one of them
240+ # MUST be set to "yes" for the system to have any
241+ # protection against the attack.
242+ #
243+ # * "yes" - Require that all Access-* packets (client and
244+ # home_server) contain Message-Authenticator. If a packet
245+ # does not contain Message-Authenticator, then it is
246+ # discarded.
247+ #
248+ # * "auto" - Automatically determine the value of the flag,
249+ # based on the first packet received from that client or
250+ # home_server.
251+ #
252+ # If the packet does not contain Message-Authenticator,
253+ # then the value of the flag is automatically switched to
254+ # "no".
255+ #
256+ # If the packet contains Message-Authenticator but not
257+ # EAP-Message, then the value of the flag is automatically
258+ # switched to "yes". The server has to check for
259+ # EAP-Message, because the previous RFCs require that the
260+ # packet contains Message-Authenticator when it also
261+ # contains EAP-Message. So having a Message-Authenticator
262+ # in those packets doesn't give the server enough
263+ # information to determined if the client or home_server
264+ # has been updated.
265+ #
266+ # If the packet contains Message-Authenticator and
267+ # EAP-Message, then the flag is left at the "auto" value.
268+ #
269+ # WARNING: This switch is done for the first packet
270+ # received from that client or home server. The change
271+ # does NOT persist across server restarts. You MUST change
272+ # the to "yes" manually, in order to make a permanent
273+ # change to the configuration.
274+ #
275+ # WARNING: If there are multiple NASes with the same source
276+ # IP and client definitions, BUT the NASes have different
277+ # behavior, then this flag WILL LIKELY BREAK YOUR NETWORK.
278+ #
279+ # That is, when there are multiple different RADIUS clients
280+ # behind one NATed IP address, then these security settings
281+ # have to be set to allow the MOST INSECURE packets to be
282+ # processed. This is a terrible idea, and will leave your
283+ # network vulnerable to the attack. Please upgrade all
284+ # clients immediately.
285+ #
286+ # The only solution to that rare configuration is to set
287+ # this flag to "no", in which case the network will work,
288+ # but will be vulnerable to the attack.
289+ #
290+ require_message_authenticator = auto
291+
292+ #
293+ # Global configuration for limiting the combination of
294+ # Proxy-State and Message-Authenticator. This flag only
295+ # applies to packets sent over UDP or TCP. This flag is
296+ # ignored for TLS.
297+ #
298+ # This flag sets the global default for all clients. It can
299+ # be over-ridden in an individual client definition by adding
300+ # the same flag to that section with an appropriate value.
301+ #
302+ # If "require_message_authenticator" is set to "yes", this
303+ # configuration item is ignored.
304+ #
305+ # If "require_message_authenticator" is set to "no", this
306+ # configuration item is checked.
307+ #
308+ # The possible values and meanings for "limit_proxy_state" are;
309+ #
310+ # * "no" - allow any packets from the client, even packets
311+ # which contain the BlastRADIUS attack. Please be aware
312+ # that in this configuration the server will complain for
313+ # EVERY packet which it receives.
314+ #
315+ # The only reason to set this flag to "no" is when the
316+ # client is a proxy, AND the proxy does not send
317+ # Message-Authenticator in Access-Request packets. Even
318+ # then, the best approach to fix the issue is to (1) update
319+ # the proxy to send Message-Authenticator, and if that
320+ # can't be done, then (2) set this flag to "no", but ONLY
321+ # for that one client. The global flag SHOULD still be set
322+ # to a safe value: "yes".
323+ #
324+ # WARNING: Setting both this flag and the
325+ # "require_message_authenticator" flag to "no" will allow
326+ # MITM attackers to create fake Access-Accept packets to the
327+ # NAS! At least one of them MUST be set to "yes" for the
328+ # system to have any protection against the attack.
329+ #
330+ # * "yes" - Allow packets without Message-Authenticator,
331+ # but only when they do not contain Proxy-State.
332+ # packets which contain Proxy-State MUST also contain
333+ # Message-Authenticator, otherwise they are discarded.
334+ #
335+ # This setting is safe for most NASes, GGSNs, BRAS, etc.
336+ # Most regular RADIUS clients do not send Proxy-State
337+ # attributes for Access-Request packets that they originate.
338+ # However some aggregators (e.g. Wireless LAN Controllers)
339+ # may act as a RADIUS proxy for requests from their cohort
340+ # of managed devices, and in such cases will provide a
341+ # Proxy-State attribute. For those systems, you _must_ look
342+ # at the actual packets to determine what to do. It may be
343+ # that the only way to fix the vulnerability is to upgrade
344+ # the WLC, and set "require_message_authenticator" to "yes".
345+ #
346+ # * "auto" - Automatically determine the value of the flag,
347+ # based on the first packet received from that client.
348+ #
349+ # If the packet contains Proxy-State but no
350+ # Message-Authenticator, then the value of the flag is
351+ # automatically switched to "no".
352+ #
353+ # For all other situations, the value of the flag is
354+ # automatically switched to "yes".
355+ #
356+ # WARNING: This switch is done for the first packet
357+ # received from that client. The change does NOT persist
358+ # across server restarts. You MUST change the to "yes"
359+ # manually, in order to make a permanent change to the
360+ # configuration.
361+ #
362+ # WARNING: If there are multiple NASes with the same source
363+ # IP and client definitions, BUT the NASes have different
364+ # behavior, then this flag WILL LIKELY BREAK YOUR NETWORK.
365+ #
366+ # That is, when there are multiple different RADIUS clients
367+ # behind one NATed IP address, then these security settings
368+ # have to be set to allow the MOST INSECURE packets to be
369+ # processed. This is a terrible idea, and will leave your
370+ # network vulnerable to the attack. Please upgrade all
371+ # clients immediately.
372+ #
373+ # The only solution to that rare configuration is to set
374+ # this flag to "no", in which case the network will work,
375+ # but will be vulnerable to the attack.
376+ #
377+ limit_proxy_state = auto
378+
379 @openssl_version_check_config@
380 }
381
382diff --git a/src/include/clients.h b/src/include/clients.h
383index 560211557f..0aeb1da8d9 100644
384--- a/src/include/clients.h
385+++ b/src/include/clients.h
386@@ -39,7 +39,11 @@ typedef struct radclient {
387
388 char const *secret; //!< Secret PSK.
389
390- bool message_authenticator; //!< Require RADIUS message authenticator in requests.
391+ fr_bool_auto_t require_ma; //!< Require RADIUS message authenticator in requests.
392+
393+ bool dynamic_require_ma; //!< for dynamic clients
394+
395+ fr_bool_auto_t limit_proxy_state; //!< Limit Proxy-State in requests
396
397 char const *nas_type; //!< Type of client (arbitrary).
398
399diff --git a/src/include/conffile.h b/src/include/conffile.h
400index 8cb045c946..ddbcae4e4f 100644
401--- a/src/include/conffile.h
402+++ b/src/include/conffile.h
403@@ -140,6 +140,7 @@ typedef struct timeval _timeval_t;
404 #define PW_TYPE_MULTI (1 << 18) //!< CONF_PAIR can have multiple copies.
405 #define PW_TYPE_NOT_EMPTY (1 << 19) //!< CONF_PAIR is required to have a non zero length value.
406 #define PW_TYPE_FILE_EXISTS ((1 << 20) | PW_TYPE_STRING) //!< File matching value must exist
407+#define PW_TYPE_IGNORE_DEFAULT (1 << 21) //!< don't set from .dflt if the CONF_PAIR is missing
408 /* @} **/
409
410 #define FR_INTEGER_COND_CHECK(_name, _var, _cond, _new)\
411diff --git a/src/include/libradius.h b/src/include/libradius.h
412index ce2f713de1..2efef8b1d3 100644
413--- a/src/include/libradius.h
414+++ b/src/include/libradius.h
415@@ -402,6 +402,10 @@ typedef struct radius_packet {
416 size_t partial;
417 int proto;
418 #endif
419+ bool tls; //!< uses secure transport
420+ bool message_authenticator;
421+ bool proxy_state;
422+ bool eap_message;
423 } RADIUS_PACKET;
424
425 typedef enum {
426@@ -507,6 +511,13 @@ DICT_VENDOR *dict_vendorbyvalue(int vendor);
427 /* radius.c */
428 int rad_send(RADIUS_PACKET *, RADIUS_PACKET const *, char const *secret);
429 bool rad_packet_ok(RADIUS_PACKET *packet, int flags, decode_fail_t *reason);
430+
431+/*
432+ * 1 == require_ma
433+ * 2 == msg_peek
434+ * 4 == limit_proxy_state
435+ * 8 == require_ma for Access-* replies and Protocol-Error
436+ */
437 RADIUS_PACKET *rad_recv(TALLOC_CTX *ctx, int fd, int flags);
438 ssize_t rad_recv_header(int sockfd, fr_ipaddr_t *src_ipaddr, uint16_t *src_port, int *code);
439 void rad_recv_discard(int sockfd);
440@@ -694,7 +705,7 @@ extern bool fr_dns_lookups; /* do IP -> hostname lookups? */
441 extern bool fr_hostname_lookups; /* do hostname -> IP lookups? */
442 extern int fr_debug_lvl; /* 0 = no debugging information */
443 extern uint32_t fr_max_attributes; /* per incoming packet */
444-#define FR_MAX_PACKET_CODE (52)
445+#define FR_MAX_PACKET_CODE (53)
446 extern char const *fr_packet_codes[FR_MAX_PACKET_CODE];
447 #define is_radius_code(_x) ((_x > 0) && (_x < FR_MAX_PACKET_CODE))
448 extern FILE *fr_log_fp;
449@@ -932,6 +943,12 @@ int fr_socket_wait_for_connect(int sockfd, struct timeval *timeout);
450 }
451 #endif
452
453+typedef enum {
454+ FR_BOOL_FALSE = 0,
455+ FR_BOOL_TRUE,
456+ FR_BOOL_AUTO,
457+} fr_bool_auto_t;
458+
459 #include <freeradius-devel/packet.h>
460
461 #ifdef WITH_TCP
462diff --git a/src/include/radius.h b/src/include/radius.h
463index 473528d65d..147d674eed 100644
464--- a/src/include/radius.h
465+++ b/src/include/radius.h
466@@ -61,6 +61,7 @@ typedef enum {
467 PW_CODE_COA_REQUEST = 43, //!< RFC3575/RFC5176 - CoA-Request
468 PW_CODE_COA_ACK = 44, //!< RFC3575/RFC5176 - CoA-Ack (positive)
469 PW_CODE_COA_NAK = 45, //!< RFC3575/RFC5176 - CoA-Nak (not willing to perform)
470+ PW_CODE_PROTOCOL_ERROR = 52, //!< RFC7930 - Protocol layer issue
471 PW_CODE_MAX = 255, //!< Maximum possible code
472 } PW_CODE;
473
474diff --git a/src/include/radiusd.h b/src/include/radiusd.h
475index b2a0a0f642..e429c5be7a 100644
476--- a/src/include/radiusd.h
477+++ b/src/include/radiusd.h
478@@ -171,6 +171,10 @@ typedef struct main_config {
479
480 bool exiting; //!< are we exiting?
481
482+ fr_bool_auto_t require_ma; //!< global configuration for all clients and home servers
483+
484+ fr_bool_auto_t limit_proxy_state; //!< global configuration for all clients
485+
486
487 #ifdef ENABLE_OPENSSL_VERSION_CHECK
488 char const *allow_vulnerable_openssl; //!< The CVE number of the last security issue acknowledged.
489@@ -558,6 +562,8 @@ int main_config_free(void);
490 void main_config_hup(void);
491 void hup_logfile(void);
492
493+int fr_bool_auto_parse(CONF_PAIR *cp, fr_bool_auto_t *out, char const *str);
494+
495 /* listen.c */
496 void listen_free(rad_listen_t **head);
497 int listen_init(CONF_SECTION *cs, rad_listen_t **head, bool spawn_flag);
498diff --git a/src/include/realms.h b/src/include/realms.h
499index 6dae8b4f85..e643818e43 100644
500--- a/src/include/realms.h
501+++ b/src/include/realms.h
502@@ -59,6 +59,7 @@ typedef struct home_server {
503 //!< stats or when specifying home servers for a pool.
504
505 bool dual; //!< One of a pair of homeservers on consecutive ports.
506+ fr_bool_auto_t require_ma; //!< for all replies to Access-Request and Status-Server
507 char const *server; //!< For internal proxying
508 char const *parent_server;
509
510diff --git a/src/lib/radius.c b/src/lib/radius.c
511index 3881111f7d..7b91a4bde2 100644
512--- a/src/lib/radius.c
513+++ b/src/lib/radius.c
514@@ -142,8 +142,9 @@ char const *fr_packet_codes[FR_MAX_PACKET_CODE] = {
515 "47",
516 "48",
517 "49",
518- "IP-Address-Allocate",
519- "IP-Address-Release", //!< 50
520+ "IP-Address-Allocate", //!< 50
521+ "IP-Address-Release",
522+ "Protocol-Error",
523 };
524
525
526@@ -1700,6 +1701,15 @@ int rad_vp2attr(RADIUS_PACKET const *packet, RADIUS_PACKET const *original,
527 return rad_vp2vsa(packet, original, secret, pvp, start, room);
528 }
529
530+static const bool code2ma[FR_MAX_PACKET_CODE] = {
531+ [ PW_CODE_ACCESS_REQUEST ] = true,
532+ [ PW_CODE_ACCESS_ACCEPT ] = true,
533+ [ PW_CODE_ACCESS_REJECT ] = true,
534+ [ PW_CODE_ACCESS_CHALLENGE ] = true,
535+ [ PW_CODE_STATUS_SERVER ] = true,
536+ [ PW_CODE_PROTOCOL_ERROR ] = true,
537+};
538+
539
540 /** Encode a packet
541 *
542@@ -1712,6 +1722,7 @@ int rad_encode(RADIUS_PACKET *packet, RADIUS_PACKET const *original,
543 uint16_t total_length;
544 int len;
545 VALUE_PAIR const *reply;
546+ bool seen_ma = false;
547
548 /*
549 * A 4K packet, aligned on 64-bits.
550@@ -1775,6 +1786,27 @@ int rad_encode(RADIUS_PACKET *packet, RADIUS_PACKET const *original,
551 * memcpy.
552 */
553
554+ /*
555+ * Always add Message-Authenticator for replies to
556+ * Access-Request packets, and for all Access-Accept,
557+ * Access-Reject, Access-Challenge.
558+ *
559+ * It must be the FIRST attribute in the packet.
560+ */
561+ if (!packet->tls &&
562+ ((code2ma[packet->code]) || (original && code2ma[original->code]))) {
563+ seen_ma = true;
564+
565+ packet->offset = RADIUS_HDR_LEN;
566+
567+ ptr[0] = PW_MESSAGE_AUTHENTICATOR;
568+ ptr[1] = 18;
569+ memset(ptr + 2, 0, 16);
570+
571+ ptr += 18;
572+ total_length += 18;
573+ }
574+
575 /*
576 * Loop over the reply attributes for the packet.
577 */
578@@ -1832,6 +1864,13 @@ int rad_encode(RADIUS_PACKET *packet, RADIUS_PACKET const *original,
579 * length and initial value.
580 */
581 if (!reply->da->vendor && (reply->da->attr == PW_MESSAGE_AUTHENTICATOR)) {
582+ /*
583+ * We have already encoded the Message-Authenticator, don't do it again.
584+ */
585+ if (seen_ma) {
586+ reply = reply->next;
587+ continue;
588+ }
589 if (room < 18) break;
590
591 /*
592@@ -2323,6 +2362,8 @@ bool rad_packet_ok(RADIUS_PACKET *packet, int flags, decode_fail_t *reason)
593 radius_packet_t *hdr;
594 char host_ipaddr[128];
595 bool require_ma = false;
596+ bool limit_proxy_state = false;
597+ bool seen_proxy_state = false;
598 bool seen_ma = false;
599 uint32_t num_attributes;
600 decode_fail_t failure = DECODE_FAIL_NONE;
601@@ -2371,15 +2412,26 @@ bool rad_packet_ok(RADIUS_PACKET *packet, int flags, decode_fail_t *reason)
602 }
603
604 /*
605- * Message-Authenticator is required in Status-Server
606- * packets, otherwise they can be trivially forged.
607+ * If the caller requires Message-Authenticator, then set
608+ * the flag.
609 */
610- if (hdr->code == PW_CODE_STATUS_SERVER) require_ma = true;
611
612 /*
613- * It's also required if the caller asks for it.
614+ * We also require Message-Authenticator if the packet
615+ * code is Status-Server.
616+ *
617+ * If we're receiving packets from a proxy socket, then
618+ * require Message-Authenticator for Access-* replies,
619+ * and for Protocol-Error.
620 */
621- if (flags) require_ma = true;
622+ require_ma = ((flags & 0x01) != 0) || (hdr->code == PW_CODE_STATUS_SERVER) || (((flags & 0x08) != 0) && code2ma[hdr->code]);
623+
624+ /*
625+ *
626+ * We only limit Proxy-State if we're not requiring
627+ * Message-Authenticator.
628+ */
629+ limit_proxy_state = ((flags & 0x04) != 0) && !require_ma;
630
631 /*
632 * Repeat the length checks. This time, instead of
633@@ -2534,6 +2586,7 @@ bool rad_packet_ok(RADIUS_PACKET *packet, int flags, decode_fail_t *reason)
634 case PW_EAP_MESSAGE:
635 require_ma = true;
636 eap = true;
637+ packet->eap_message = true;
638 break;
639
640 case PW_USER_PASSWORD:
641@@ -2542,6 +2595,11 @@ bool rad_packet_ok(RADIUS_PACKET *packet, int flags, decode_fail_t *reason)
642 non_eap = true;
643 break;
644
645+ case PW_PROXY_STATE:
646+ seen_proxy_state = true;
647+ packet->proxy_state = true;
648+ break;
649+
650 case PW_MESSAGE_AUTHENTICATOR:
651 if (attr[1] != 2 + AUTH_VECTOR_LEN) {
652 FR_DEBUG_STRERROR_PRINTF("Malformed RADIUS packet from host %s: Message-Authenticator has invalid length %d",
653@@ -2553,6 +2611,7 @@ bool rad_packet_ok(RADIUS_PACKET *packet, int flags, decode_fail_t *reason)
654 goto finish;
655 }
656 seen_ma = true;
657+ packet->message_authenticator = true;
658 break;
659 }
660
661@@ -2609,7 +2668,19 @@ bool rad_packet_ok(RADIUS_PACKET *packet, int flags, decode_fail_t *reason)
662 * Message-Authenticator attributes.
663 */
664 if (require_ma && !seen_ma) {
665- FR_DEBUG_STRERROR_PRINTF("Insecure packet from host %s: Packet does not contain required Message-Authenticator attribute",
666+ FR_DEBUG_STRERROR_PRINTF("Insecure packet from host %s: Packet does not contain required Message-Authenticator attribute. You may need to set \"require_message_authenticator = no\" in the configuration.",
667+ inet_ntop(packet->src_ipaddr.af,
668+ &packet->src_ipaddr.ipaddr,
669+ host_ipaddr, sizeof(host_ipaddr)));
670+ failure = DECODE_FAIL_MA_MISSING;
671+ goto finish;
672+ }
673+
674+ /*
675+ * The client is a NAS which shouldn't send Proxy-State, but it did!
676+ */
677+ if (limit_proxy_state && seen_proxy_state && !seen_ma) {
678+ FR_DEBUG_STRERROR_PRINTF("Insecure packet from host %s: Packet does not contain required Message-Authenticator attribute, but still has one or more Proxy-State attributes",
679 inet_ntop(packet->src_ipaddr.af,
680 &packet->src_ipaddr.ipaddr,
681 host_ipaddr, sizeof(host_ipaddr)));
682diff --git a/src/main/client.c b/src/main/client.c
683index 6228438c47..875dc37d60 100644
684--- a/src/main/client.c
685+++ b/src/main/client.c
686@@ -283,7 +283,8 @@ bool client_add(RADCLIENT_LIST *clients, RADCLIENT *client)
687 (old->coa_server == client->coa_server) &&
688 (old->coa_pool == client->coa_pool) &&
689 #endif
690- (old->message_authenticator == client->message_authenticator)) {
691+ (old->require_ma == client->require_ma) &&
692+ (old->limit_proxy_state == client->limit_proxy_state)) {
693 WARN("Ignoring duplicate client %s", client->longname);
694 client_free(client);
695 return true;
696@@ -445,6 +446,8 @@ static fr_ipaddr_t cl_ipaddr;
697 static uint32_t cl_netmask;
698 static char const *cl_srcipaddr = NULL;
699 static char const *hs_proto = NULL;
700+static char const *require_message_authenticator = NULL;
701+static char const *limit_proxy_state = NULL;
702
703 #ifdef WITH_TCP
704 static CONF_PARSER limit_config[] = {
705@@ -467,7 +470,8 @@ static const CONF_PARSER client_config[] = {
706
707 { "src_ipaddr", FR_CONF_POINTER(PW_TYPE_STRING, &cl_srcipaddr), NULL },
708
709- { "require_message_authenticator", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, RADCLIENT, message_authenticator), "no" },
710+ { "require_message_authenticator", FR_CONF_POINTER(PW_TYPE_STRING| PW_TYPE_IGNORE_DEFAULT, &require_message_authenticator), NULL },
711+ { "limit_proxy_state", FR_CONF_POINTER(PW_TYPE_STRING| PW_TYPE_IGNORE_DEFAULT, &limit_proxy_state), NULL },
712
713 { "secret", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_SECRET, RADCLIENT, secret), NULL },
714 { "shortname", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, shortname), NULL },
715@@ -663,7 +667,7 @@ static const CONF_PARSER dynamic_config[] = {
716 { "FreeRADIUS-Client-Src-IP-Address", FR_CONF_OFFSET(PW_TYPE_IPV4_ADDR, RADCLIENT, src_ipaddr), NULL },
717 { "FreeRADIUS-Client-Src-IPv6-Address", FR_CONF_OFFSET(PW_TYPE_IPV6_ADDR, RADCLIENT, src_ipaddr), NULL },
718
719- { "FreeRADIUS-Client-Require-MA", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, RADCLIENT, message_authenticator), NULL },
720+ { "FreeRADIUS-Client-Require-MA", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, RADCLIENT, dynamic_require_ma), NULL },
721
722 { "FreeRADIUS-Client-Secret", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, secret), "" },
723 { "FreeRADIUS-Client-Shortname", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, shortname), "" },
724@@ -845,8 +849,19 @@ RADCLIENT *client_afrom_cs(TALLOC_CTX *ctx, CONF_SECTION *cs, bool in_server, bo
725 c = talloc_zero(ctx, RADCLIENT);
726 c->cs = cs;
727
728+ /*
729+ * Set the "require message authenticator" and "limit
730+ * proxy state" flags from the global default. If the
731+ * configuration item exists, AND is set, it will
732+ * over-ride the flag.
733+ */
734+ c->require_ma = main_config.require_ma;
735+ c->limit_proxy_state = main_config.limit_proxy_state;
736+
737 memset(&cl_ipaddr, 0, sizeof(cl_ipaddr));
738 cl_netmask = 255;
739+ require_message_authenticator = NULL;
740+ limit_proxy_state = NULL;
741
742 if (cf_section_parse(cs, c, client_config) < 0) {
743 cf_log_err_cs(cs, "Error parsing client section");
744@@ -857,6 +872,9 @@ RADCLIENT *client_afrom_cs(TALLOC_CTX *ctx, CONF_SECTION *cs, bool in_server, bo
745 cl_srcipaddr = NULL;
746 #endif
747
748+ require_message_authenticator = NULL;
749+ limit_proxy_state = NULL;
750+
751 return NULL;
752 }
753
754@@ -1114,6 +1132,16 @@ done_coa:
755 }
756 #endif
757
758+ if (fr_bool_auto_parse(cf_pair_find(cs, "require_message_authenticator"), &c->require_ma, require_message_authenticator) < 0) {
759+ goto error;
760+ }
761+
762+ if (c->require_ma != FR_BOOL_TRUE) {
763+ if (fr_bool_auto_parse(cf_pair_find(cs, "limit_proxy_state"), &c->limit_proxy_state, limit_proxy_state) < 0) {
764+ goto error;
765+ }
766+ }
767+
768 return c;
769 }
770
771@@ -1158,7 +1186,7 @@ RADCLIENT *client_afrom_query(TALLOC_CTX *ctx, char const *identifier, char cons
772 if (shortname) c->shortname = talloc_typed_strdup(c, shortname);
773 if (type) c->nas_type = talloc_typed_strdup(c, type);
774 if (server) c->server = talloc_typed_strdup(c, server);
775- c->message_authenticator = require_ma;
776+ c->require_ma = require_ma;
777
778 return c;
779 }
780@@ -1344,10 +1372,10 @@ RADCLIENT *client_afrom_request(RADCLIENT_LIST *clients, REQUEST *request)
781 *pi = vp->vp_integer;
782
783 /*
784- * Same nastiness as above.
785+ * Same nastiness as above, but hard-coded for require Message-Authenticator.
786 */
787 for (parse = client_config; parse->name; parse++) {
788- if (parse->offset == dynamic_config[i].offset) break;
789+ if (parse->type == PW_TYPE_BOOLEAN) break;
790 }
791 if (!parse) break;
792
793@@ -1436,6 +1464,11 @@ validate:
794 goto error;
795 }
796
797+ /*
798+ * It can't be set to "auto". Too bad.
799+ */
800+ c->require_ma = (fr_bool_auto_t) c->dynamic_require_ma;
801+
802 if (!client_add_dynamic(clients, request->client, c)) {
803 return NULL;
804 }
805diff --git a/src/main/conffile.c b/src/main/conffile.c
806index a8c667bfb5..61754e991f 100644
807--- a/src/main/conffile.c
808+++ b/src/main/conffile.c
809@@ -1418,6 +1418,7 @@ int cf_item_parse(CONF_SECTION *cs, char const *name, unsigned int type, void *d
810 {
811 int rcode;
812 bool deprecated, required, attribute, secret, file_input, cant_be_empty, tmpl, multi, file_exists;
813+ bool ignore_dflt;
814 char **q;
815 char const *value;
816 CONF_PAIR *cp = NULL;
817@@ -1441,6 +1442,7 @@ int cf_item_parse(CONF_SECTION *cs, char const *name, unsigned int type, void *d
818 cant_be_empty = (type & PW_TYPE_NOT_EMPTY);
819 tmpl = (type & PW_TYPE_TMPL);
820 multi = (type & PW_TYPE_MULTI);
821+ ignore_dflt = (type & PW_TYPE_IGNORE_DEFAULT);
822
823 if (attribute) required = true;
824 if (required) cant_be_empty = true; /* May want to review this in the future... */
825@@ -1464,7 +1466,7 @@ int cf_item_parse(CONF_SECTION *cs, char const *name, unsigned int type, void *d
826 * section, use the default value.
827 */
828 if (!cp) {
829- if (deprecated) return 0; /* Don't set the default value */
830+ if (deprecated || ignore_dflt) return 0; /* Don't set the default value */
831
832 rcode = 1;
833 value = dflt;
834diff --git a/src/main/listen.c b/src/main/listen.c
835index ebf7f5221c..c20fea243d 100644
836--- a/src/main/listen.c
837+++ b/src/main/listen.c
838@@ -456,6 +456,122 @@ int rad_status_server(REQUEST *request)
839 return 0;
840 }
841
842+static void blastradius_checks(RADIUS_PACKET *packet, RADCLIENT *client)
843+{
844+ if (client->require_ma == FR_BOOL_TRUE) return;
845+
846+ if (client->require_ma == FR_BOOL_AUTO) {
847+ if (!packet->message_authenticator) {
848+ ERROR("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
849+ ERROR("BlastRADIUS check: Received packet without Message-Authenticator.");
850+ ERROR("Setting \"require_message_authenticator = false\" for client %s", client->shortname);
851+ ERROR("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
852+ ERROR("UPGRADE THE CLIENT AS YOUR NETWORK IS VULNERABLE TO THE BLASTRADIUS ATTACK.");
853+ ERROR("Once the client is upgraded, set \"require_message_authenticator = true\" for client %s", client->shortname);
854+ ERROR("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
855+ client->require_ma = FR_BOOL_FALSE;
856+
857+ /*
858+ * And fall through to the
859+ * limit_proxy_state checks, which might
860+ * complain again. Oh well, maybe that
861+ * will make people read the messages.
862+ */
863+
864+ } else if (packet->eap_message) {
865+ /*
866+ * Don't set it to "true" for packets
867+ * with EAP-Message. It's already
868+ * required there, and we might get a
869+ * non-EAP packet with (or without)
870+ * Message-Authenticator
871+ */
872+ return;
873+ } else {
874+ ERROR("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
875+ ERROR("BlastRADIUS check: Received packet with Message-Authenticator.");
876+ ERROR("Setting \"require_message_authenticator = true\" for client %s", client->shortname);
877+ ERROR("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
878+ ERROR("It looks like the client has been updated to protect from the BlastRADIUS attack.");
879+ ERROR("Please set \"require_message_authenticator = true\" for client %s", client->shortname);
880+ ERROR("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
881+
882+ client->require_ma = FR_BOOL_TRUE;
883+ return;
884+ }
885+
886+ }
887+
888+ /*
889+ * If all of the checks are turned off, then complain for every packet we receive.
890+ */
891+ if (client->limit_proxy_state == FR_BOOL_FALSE) {
892+ /*
893+ * We have a Message-Authenticator, and it's valid. We don't need to compain.
894+ */
895+ if (!fr_debug_lvl) return; /* easier than checking for each line below */
896+
897+ DEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
898+ DEBUG("BlastRADIUS check: Received packet without Message-Authenticator.");
899+ DEBUG("YOU MUST SET \"require_message_authenticator = true\", or");
900+ DEBUG("YOU MUST SET \"limit_proxy_state = true\" for client %s", client->shortname);
901+ DEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
902+ DEBUG("The packet does not contain Message-Authenticator, which is a security issue");
903+ DEBUG("UPGRADE THE CLIENT AS YOUR NETWORK IS VULNERABLE TO THE BLASTRADIUS ATTACK.");
904+ DEBUG("Once the client is upgraded, set \"require_message_authenticator = true\" for client %s", client->shortname);
905+ DEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
906+ return;
907+ }
908+
909+ /*
910+ * Don't complain here. rad_packet_ok() will instead
911+ * complain about every packet with Proxy-State but which
912+ * is missing Message-Authenticator.
913+ */
914+ if (client->limit_proxy_state == FR_BOOL_TRUE) {
915+ return;
916+ }
917+
918+ if (packet->proxy_state && !packet->message_authenticator) {
919+ ERROR("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
920+ ERROR("BlastRADIUS check: Received packet with Proxy-State, but without Message-Authenticator.");
921+ ERROR("This is either a BlastRADIUS attack, OR");
922+ ERROR("the client is a proxy RADIUS server which has not been upgraded.");
923+ ERROR("Setting \"limit_proxy_state = false\" for client %s", client->shortname);
924+ ERROR("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
925+ ERROR("UPGRADE THE CLIENT AS YOUR NETWORK IS VULNERABLE TO THE BLASTRADIUS ATTACK.");
926+ DEBUG("Once the client is upgraded, set \"require_message_authenticator = true\" for client %s", client->shortname);
927+ ERROR("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
928+
929+ client->limit_proxy_state = FR_BOOL_FALSE;
930+
931+ } else {
932+ client->limit_proxy_state = FR_BOOL_TRUE;
933+
934+ ERROR("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
935+ if (!packet->proxy_state) {
936+ ERROR("BlastRADIUS check: Received packet without Proxy-State.");
937+ } else {
938+ ERROR("BlastRADIUS check: Received packet with Proxy-State and Message-Authenticator.");
939+ }
940+
941+ ERROR("Setting \"limit_proxy_state = true\" for client %s", client->shortname);
942+ ERROR("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
943+
944+ if (!packet->message_authenticator) {
945+ ERROR("The packet does not contain Message-Authenticator, which is a security issue.");
946+ ERROR("UPGRADE THE CLIENT AS YOUR NETWORK MAY BE VULNERABLE TO THE BLASTRADIUS ATTACK.");
947+ DEBUG("Once the client is upgraded, set \"require_message_authenticator = true\" for client %s", client->shortname);
948+ } else {
949+ ERROR("The packet contains Message-Authenticator.");
950+ if (!packet->eap_message) ERROR("The client has likely been upgraded to protect from the attack.");
951+ ERROR("Please set \"require_message_authenticator = true\" for client %s", client->shortname);
952+ }
953+ ERROR("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
954+ }
955+}
956+
957+
958 #ifdef WITH_TCP
959 static int dual_tcp_recv(rad_listen_t *listener)
960 {
961@@ -532,6 +648,21 @@ static int dual_tcp_recv(rad_listen_t *listener)
962 switch (packet->code) {
963 case PW_CODE_ACCESS_REQUEST:
964 if (listener->type != RAD_LISTEN_AUTH) goto bad_packet;
965+
966+ /*
967+ * Enforce BlastRADIUS checks on TCP, too.
968+ */
969+ if (!rad_packet_ok(packet, (client->require_ma == FR_BOOL_TRUE) | ((client->limit_proxy_state == FR_BOOL_TRUE) << 2), NULL)) {
970+ FR_STATS_INC(auth, total_malformed_requests);
971+ rad_free(&sock->packet);
972+ return 0;
973+ }
974+
975+ /*
976+ * Perform BlastRADIUS checks and warnings.
977+ */
978+ if (packet->code == PW_CODE_ACCESS_REQUEST) blastradius_checks(packet, client);
979+
980 FR_STATS_INC(auth, total_requests);
981 fun = rad_authenticate;
982 break;
983@@ -1562,7 +1693,7 @@ static int auth_socket_recv(rad_listen_t *listener)
984 * Now that we've sanity checked everything, receive the
985 * packet.
986 */
987- packet = rad_recv(ctx, listener->fd, client->message_authenticator);
988+ packet = rad_recv(ctx, listener->fd, (client->require_ma == FR_BOOL_TRUE) | ((client->limit_proxy_state == FR_BOOL_TRUE) << 2));
989 if (!packet) {
990 FR_STATS_INC(auth, total_malformed_requests);
991 if (DEBUG_ENABLED) ERROR("Receive - %s", fr_strerror());
992@@ -1570,6 +1701,12 @@ static int auth_socket_recv(rad_listen_t *listener)
993 return 0;
994 }
995
996+
997+ /*
998+ * Perform BlastRADIUS checks and warnings.
999+ */
1000+ if (packet->code == PW_CODE_ACCESS_REQUEST) blastradius_checks(packet, client);
1001+
1002 #ifdef __APPLE__
1003 #ifdef WITH_UDPFROMTO
1004 /*
1005@@ -1955,7 +2092,7 @@ static int coa_socket_recv(rad_listen_t *listener)
1006 * Now that we've sanity checked everything, receive the
1007 * packet.
1008 */
1009- packet = rad_recv(ctx, listener->fd, client->message_authenticator);
1010+ packet = rad_recv(ctx, listener->fd, client->require_ma | (((int) client->limit_proxy_state) << 2));
1011 if (!packet) {
1012 FR_STATS_INC(coa, total_malformed_requests);
1013 if (DEBUG_ENABLED) ERROR("Receive - %s", fr_strerror());
1014diff --git a/src/main/mainconfig.c b/src/main/mainconfig.c
1015index e9dd412dee..520d7fa474 100644
1016--- a/src/main/mainconfig.c
1017+++ b/src/main/mainconfig.c
1018@@ -73,6 +73,8 @@ static char const *gid_name = NULL;
1019 static char const *chroot_dir = NULL;
1020 static bool allow_core_dumps = false;
1021 static char const *radlog_dest = NULL;
1022+static char const *require_message_authenticator = NULL;
1023+static char const *limit_proxy_state = NULL;
1024
1025 /*
1026 * These are not used anywhere else..
1027@@ -87,6 +89,53 @@ static bool do_colourise = false;
1028
1029 static char const *radius_dir = NULL; //!< Path to raddb directory
1030
1031+static const FR_NAME_NUMBER fr_bool_auto_names[] = {
1032+ { "false", FR_BOOL_FALSE },
1033+ { "no", FR_BOOL_FALSE },
1034+ { "0", FR_BOOL_FALSE },
1035+
1036+ { "true", FR_BOOL_TRUE },
1037+ { "yes", FR_BOOL_TRUE },
1038+ { "1", FR_BOOL_TRUE },
1039+
1040+ { "auto", FR_BOOL_AUTO },
1041+
1042+ { NULL, 0 }
1043+};
1044+
1045+/*
1046+ * Get decent values for false / true / auto
1047+ */
1048+int fr_bool_auto_parse(CONF_PAIR *cp, fr_bool_auto_t *out, char const *str)
1049+{
1050+ int value;
1051+
1052+ /*
1053+ * Don't change anything.
1054+ */
1055+ if (!str) return 0;
1056+
1057+ value = fr_str2int(fr_bool_auto_names, str, -1);
1058+ if (value >= 0) {
1059+ *out = value;
1060+ return 0;
1061+ }
1062+
1063+ /*
1064+ * This should never happen, as the defaults are in the
1065+ * source code. If there's no CONF_PAIR, and there's a
1066+ * parse error, then the source code is wrong.
1067+ */
1068+ if (!cp) {
1069+ fprintf(stderr, "%s: Error - Invalid value in configuration", main_config.name);
1070+ return -1;
1071+ }
1072+
1073+ cf_log_err(cf_pair_to_item(cp), "Invalid value for \"%s\"", cf_pair_attr(cp));
1074+ return -1;
1075+}
1076+
1077+
1078 /**********************************************************************
1079 *
1080 * We need to figure out where the logs go, before doing anything
1081@@ -159,6 +208,8 @@ static const CONF_PARSER security_config[] = {
1082 { "max_attributes", FR_CONF_POINTER(PW_TYPE_INTEGER, &fr_max_attributes), STRINGIFY(0) },
1083 { "reject_delay", FR_CONF_POINTER(PW_TYPE_TIMEVAL, &main_config.reject_delay), STRINGIFY(0) },
1084 { "status_server", FR_CONF_POINTER(PW_TYPE_BOOLEAN, &main_config.status_server), "no"},
1085+ { "require_message_authenticator", FR_CONF_POINTER(PW_TYPE_STRING, &require_message_authenticator), "auto"},
1086+ { "limit_proxy_state", FR_CONF_POINTER(PW_TYPE_STRING, &limit_proxy_state), "auto"},
1087 #ifdef ENABLE_OPENSSL_VERSION_CHECK
1088 { "allow_vulnerable_openssl", FR_CONF_POINTER(PW_TYPE_STRING, &main_config.allow_vulnerable_openssl), "no"},
1089 #endif
1090@@ -838,6 +889,8 @@ int main_config_init(void)
1091 if (!main_config.dictionary_dir) {
1092 main_config.dictionary_dir = DICTDIR;
1093 }
1094+ main_config.require_ma = FR_BOOL_AUTO;
1095+ main_config.limit_proxy_state = FR_BOOL_AUTO;
1096
1097 /*
1098 * About sizeof(REQUEST) + sizeof(RADIUS_PACKET) * 2 + sizeof(VALUE_PAIR) * 400
1099@@ -1127,6 +1180,23 @@ do {\
1100 main_config.init_delay.tv_sec = 0;
1101 main_config.init_delay.tv_usec = 2* (1000000 / 3);
1102
1103+ {
1104+ CONF_PAIR *cp = NULL;
1105+
1106+ subcs = cf_section_sub_find(cs, "security");
1107+ if (subcs) cp = cf_pair_find(subcs, "require_message_authenticator");
1108+ if (fr_bool_auto_parse(cp, &main_config.require_ma, require_message_authenticator) < 0) {
1109+ cf_file_free(cs);
1110+ return -1;
1111+ }
1112+
1113+ if (subcs) cp = cf_pair_find(subcs, "limit_proxy_state");
1114+ if (fr_bool_auto_parse(cp, &main_config.limit_proxy_state, limit_proxy_state) < 0) {
1115+ cf_file_free(cs);
1116+ return -1;
1117+ }
1118+ }
1119+
1120 /*
1121 * Free the old configuration items, and replace them
1122 * with the new ones.
1123diff --git a/src/main/process.c b/src/main/process.c
1124index 1a48517d43..401033bdd6 100644
1125--- a/src/main/process.c
1126+++ b/src/main/process.c
1127@@ -2593,6 +2593,23 @@ int request_proxy_reply(RADIUS_PACKET *packet)
1128
1129 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
1130
1131+ if (!request->proxy_reply) {
1132+ decode_fail_t reason;
1133+
1134+ /*
1135+ * If the home server configuration requires a Message-Authenticator, then set the flag,
1136+ * but only if the proxied packet is Access-Request or Status-Sercer.
1137+ *
1138+ * The realms.c file already clears require_ma for TLS connections.
1139+ */
1140+ bool require_ma = (request->home_server->require_ma == FR_BOOL_TRUE) && (request->proxy->code == PW_CODE_ACCESS_REQUEST);
1141+
1142+ if(!rad_packet_ok(packet, require_ma, &reason)) {
1143+ DEBUG("Ignoring invalid packet - %s", fr_strerror());
1144+ return 0;
1145+ }
1146+ }
1147+
1148 /*
1149 * No reply, BUT the current packet fails verification:
1150 * ignore it. This does the MD5 calculations in the
1151@@ -2618,6 +2635,54 @@ int request_proxy_reply(RADIUS_PACKET *packet)
1152 return 0;
1153 }
1154
1155+
1156+ /*
1157+ * BlastRADIUS checks. We're running in the main
1158+ * listener thread, so there's no conflict
1159+ * checking or setting these fields.
1160+ */
1161+ if (!request->proxy_reply && (request->proxy->code == PW_CODE_ACCESS_REQUEST) &&
1162+#ifdef WITH_TLS
1163+ !request->home_server->tls &&
1164+#endif
1165+ !packet->eap_message) {
1166+ if (request->home_server->require_ma == FR_BOOL_AUTO) {
1167+ if (!packet->message_authenticator) {
1168+ RERROR("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1169+ RERROR("BlastRADIUS check: Received response to Access-Request without Message-Authenticator.");
1170+ RERROR("Setting \"require_message_authenticator = false\" for home_server %s", request->home_server->name);
1171+ RERROR("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1172+ RERROR("UPGRADE THE HOME SERVER AS YOUR NETWORK IS VULNERABLE TO THE BLASTRADIUS ATTACK.");
1173+ RERROR("Once the home_server is upgraded, set \"require_message_authenticator = true\" for home_server %s.", request->home_server->name);
1174+ RERROR("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1175+
1176+ request->home_server->require_ma = FR_BOOL_FALSE;
1177+ } else {
1178+ RERROR("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1179+ RERROR("BlastRADIUS check: Received response to Access-Request with Message-Authenticator.");
1180+ RERROR("Setting \"require_message_authenticator = true\" for home_server %s", request->home_server->name);
1181+ RERROR("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1182+ RERROR("It looks like the home server has been updated to protect from the BlastRADIUS attack.");
1183+ RERROR("Please set \"require_message_authenticator = true\" for home_server %s", request->home_server->name);
1184+ RERROR("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1185+
1186+ request->home_server->require_ma = FR_BOOL_TRUE;
1187+ }
1188+
1189+ } else if (fr_debug_lvl && (request->home_server->require_ma == FR_BOOL_FALSE) && !packet->message_authenticator) {
1190+ /*
1191+ * If it's "no" AND we don't have a Message-Authenticator, then complain on every packet.
1192+ */
1193+ RDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1194+ RDEBUG("BlastRADIUS check: Received packet without Message-Authenticator from home_server %s", request->home_server->name);
1195+ RDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1196+ RDEBUG("The packet does not contain Message-Authenticator, which is a security issue");
1197+ RDEBUG("UPGRADE THE HOME SERVER AS YOUR NETWORK IS VULNERABLE TO THE BLASTRADIUS ATTACK.");
1198+ RERROR("Once the home_server is upgraded, set \"require_message_authenticator = true\" for home_server %s.", request->home_server->name);
1199+ RDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1200+ }
1201+ }
1202+
1203 /*
1204 * This shouldn't happen, but threads and race
1205 * conditions.
1206diff --git a/src/main/radclient.c b/src/main/radclient.c
1207index 52d2872b13..47d5f07785 100644
1208--- a/src/main/radclient.c
1209+++ b/src/main/radclient.c
1210@@ -54,6 +54,7 @@ static fr_ipaddr_t server_ipaddr;
1211 static int resend_count = 1;
1212 static bool done = true;
1213 static bool print_filename = false;
1214+static bool blast_radius = false;
1215
1216 static fr_ipaddr_t client_ipaddr;
1217 static uint16_t client_port = 0;
1218@@ -89,6 +90,7 @@ static void NEVER_RETURNS usage(void)
1219 fprintf(stderr, " <command> One of auth, acct, status, coa, disconnect or auto.\n");
1220 fprintf(stderr, " -4 Use IPv4 address of server\n");
1221 fprintf(stderr, " -6 Use IPv6 address of server.\n");
1222+ fprintf(stderr, " -b Mandate checks for Blast RADIUS (this is not set by default).\n");
1223 fprintf(stderr, " -c <count> Send each packet 'count' times.\n");
1224 fprintf(stderr, " -d <raddb> Set user dictionary directory (defaults to " RADDBDIR ").\n");
1225 fprintf(stderr, " -D <dictdir> Set main dictionary directory (defaults to " DICTDIR ").\n");
1226@@ -1000,6 +1002,130 @@ static int send_one_packet(rc_request_t *request)
1227 return 0;
1228 }
1229
1230+/*
1231+ * Do Blast RADIUS checks.
1232+ *
1233+ * The request is an Access-Request, and does NOT contain Proxy-State.
1234+ *
1235+ * The reply is a raw packet, and is NOT yet decoded.
1236+ */
1237+static int blast_radius_check(rc_request_t *request, RADIUS_PACKET *reply)
1238+{
1239+ uint8_t *attr, *end;
1240+ VALUE_PAIR *vp;
1241+ bool have_message_authenticator = false;
1242+
1243+ /*
1244+ * We've received a raw packet. Nothing has (as of yet) checked
1245+ * anything in it other than the length, and that it's a
1246+ * well-formed RADIUS packet.
1247+ */
1248+ switch (reply->data[0]) {
1249+ case PW_CODE_ACCESS_ACCEPT:
1250+ case PW_CODE_ACCESS_REJECT:
1251+ case PW_CODE_ACCESS_CHALLENGE:
1252+ if (reply->data[1] != request->packet->id) {
1253+ ERROR("Invalid reply ID %d to Access-Request ID %d", reply->data[1], request->packet->id);
1254+ return -1;
1255+ }
1256+ break;
1257+
1258+ default:
1259+ ERROR("Invalid reply code %d to Access-Request", reply->data[0]);
1260+ return -1;
1261+ }
1262+
1263+ /*
1264+ * If the reply has a Message-Authenticator, then it MIGHT be fine.
1265+ */
1266+ attr = reply->data + 20;
1267+ end = reply->data + reply->data_len;
1268+
1269+ /*
1270+ * It should be the first attribute, so we warn if it isn't there.
1271+ *
1272+ * But it's not a fatal error.
1273+ */
1274+ if (blast_radius && (attr[0] != PW_MESSAGE_AUTHENTICATOR)) {
1275+ RDEBUG("WARNING The %s reply packet does not have Message-Authenticator as the first attribute. The packet may be vulnerable to Blast RADIUS attacks.",
1276+ fr_packet_codes[reply->data[0]]);
1277+ }
1278+
1279+ /*
1280+ * Set up for Proxy-State checks.
1281+ *
1282+ * If we see a Proxy-State in the reply which we didn't send, then it's a Blast RADIUS attack.
1283+ */
1284+ vp = fr_pair_find_by_num(request->packet->vps, PW_PROXY_STATE, 0, TAG_ANY);
1285+
1286+ while (attr < end) {
1287+ /*
1288+ * Blast RADIUS work-arounds require that
1289+ * Message-Authenticator is the first attribute in the
1290+ * reply. Note that we don't check for it being the
1291+ * first attribute, but simply that it exists.
1292+ *
1293+ * That check is a balance between securing the reply
1294+ * packet from attacks, and not violating the RFCs which
1295+ * say that there is no order to attributes in the
1296+ * packet.
1297+ *
1298+ * However, no matter the status of the '-b' flag we
1299+ * still can check for the signature of the attack, and
1300+ * discard packets which are suspicious. This behavior
1301+ * protects radclient from the attack, without mandating
1302+ * new behavior on the server side.
1303+ *
1304+ * Note that we don't set the '-b' flag by default.
1305+ * radclient is intended for testing / debugging, and is
1306+ * not intended to be used as part of a secure login /
1307+ * user checking system.
1308+ */
1309+ if (attr[0] == PW_MESSAGE_AUTHENTICATOR) {
1310+ have_message_authenticator = true;
1311+ goto next;
1312+ }
1313+
1314+ /*
1315+ * If there are Proxy-State attributes in the reply, they must
1316+ * match EXACTLY the Proxy-State attributes in the request.
1317+ *
1318+ * Note that we don't care if there are more Proxy-States
1319+ * in the request than in the reply. The Blast RADIUS
1320+ * issue requires _adding_ Proxy-State attributes, and
1321+ * cannot work when the server _deletes_ Proxy-State
1322+ * attributes.
1323+ */
1324+ if (attr[0] == PW_PROXY_STATE) {
1325+ if (!vp || (vp->length != (size_t) (attr[1] - 2)) || (memcmp(vp->vp_octets, attr + 2, vp->length) != 0)) {
1326+ ERROR("Invalid reply to Access-Request ID %d - Discarding packet due to Blast RADIUS attack being detected.", request->packet->id);
1327+ ERROR("We received a Proxy-State in the reply which we did not send, or which is different from what we sent.");
1328+ return -1;
1329+ }
1330+
1331+ vp = fr_pair_find_by_num(vp->next, PW_PROXY_STATE, 0, TAG_ANY);
1332+ }
1333+
1334+ next:
1335+ attr += attr[1];
1336+ }
1337+
1338+ /*
1339+ * If "-b" is set, then we require Message-Authenticator in the reply.
1340+ */
1341+ if (blast_radius && !have_message_authenticator) {
1342+ ERROR("The %s reply packet does not contain Message-Authenticator - discarding packet due to Blast RADIUS checks.",
1343+ fr_packet_codes[reply->data[0]]);
1344+ return -1;
1345+ }
1346+
1347+ /*
1348+ * The packet doesn't look like it's a Blast RADIUS attack. The
1349+ * caller will now verify the packet signature.
1350+ */
1351+ return 0;
1352+}
1353+
1354 /*
1355 * Receive one packet, maybe.
1356 */
1357@@ -1051,6 +1177,21 @@ static int recv_one_packet(int wait_time)
1358 }
1359 request = fr_packet2myptr(rc_request_t, packet, packet_p);
1360
1361+
1362+ /*
1363+ * We want radclient to be able to send any packet, including
1364+ * imperfect ones. However, we do NOT want to be vulnerable to
1365+ * the "Blast RADIUS" issue. Instead of adding command-line
1366+ * flags to enable/disable similar flags to what the server
1367+ * sends, we just do a few more smart checks to double-check
1368+ * things.
1369+ */
1370+ if ((request->packet->code == PW_CODE_ACCESS_REQUEST) &&
1371+ blast_radius_check(request, reply) < 0) {
1372+ rad_free(&reply);
1373+ return -1;
1374+ }
1375+
1376 /*
1377 * Fails the signature validation: not a real reply.
1378 * FIXME: Silently drop it and listen for another packet.
1379@@ -1183,7 +1324,7 @@ int main(int argc, char **argv)
1380 exit(1);
1381 }
1382
1383- while ((c = getopt(argc, argv, "46c:d:D:f:Fhn:p:qr:sS:t:vx"
1384+ while ((c = getopt(argc, argv, "46bc:d:D:f:Fhn:p:qr:sS:t:vx"
1385 #ifdef WITH_TCP
1386 "P:"
1387 #endif
1388@@ -1192,6 +1333,10 @@ int main(int argc, char **argv)
1389 force_af = AF_INET;
1390 break;
1391
1392+ case 'b':
1393+ blast_radius = true;
1394+ break;
1395+
1396 case '6':
1397 force_af = AF_INET6;
1398 break;
1399diff --git a/src/main/radtest.in b/src/main/radtest.in
1400index 38b1ba9a0f..8a6741a26c 100644
1401--- a/src/main/radtest.in
1402+++ b/src/main/radtest.in
1403@@ -19,6 +19,7 @@ usage() {
1404 echo " -x Enable debug output" >&2
1405 echo " -4 Use IPv4 for the NAS address (default)" >&2
1406 echo " -6 Use IPv6 for the NAS address" >&2
1407+ echo " -6 Mandate checks for Blast RADIUS (this is not set by default)." >&2
1408 exit 1
1409 }
1410
1411@@ -55,6 +56,10 @@ do
1412 NAS_ADDR_ATTR="NAS-IPv6-Address"
1413 shift
1414 ;;
1415+ -b)
1416+ OPTIONS="$OPTIONS -b"
1417+ shift
1418+ ;;
1419 -d)
1420 OPTIONS="$OPTIONS -d $2"
1421 shift;shift
1422@@ -120,7 +125,6 @@ fi
1423 echo "$PASSWORD = \"$2\""
1424 echo "$NAS_ADDR_ATTR = $nas"
1425 echo "NAS-Port = $4"
1426- echo "Message-Authenticator = 0x00"
1427 if [ "$radclient" = "$radeapclient" ]
1428 then
1429 echo "EAP-Code = Response"
1430diff --git a/src/main/realms.c b/src/main/realms.c
1431index eb42598116..5e1215c0bb 100644
1432--- a/src/main/realms.c
1433+++ b/src/main/realms.c
1434@@ -366,7 +366,10 @@ static CONF_PARSER home_server_coa[] = {
1435 };
1436 #endif
1437
1438+static const char *require_message_authenticator = NULL;
1439+
1440 static CONF_PARSER home_server_config[] = {
1441+ { "require_message_authenticator", FR_CONF_POINTER(PW_TYPE_STRING| PW_TYPE_IGNORE_DEFAULT, &require_message_authenticator), NULL },
1442 { "ipaddr", FR_CONF_OFFSET(PW_TYPE_COMBO_IP_ADDR, home_server_t, ipaddr), NULL },
1443 { "ipv4addr", FR_CONF_OFFSET(PW_TYPE_IPV4_ADDR, home_server_t, ipaddr), NULL },
1444 { "ipv6addr", FR_CONF_OFFSET(PW_TYPE_IPV6_ADDR, home_server_t, ipaddr), NULL },
1445@@ -640,6 +643,9 @@ home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SE
1446 home->cs = cs;
1447 home->state = HOME_STATE_UNKNOWN;
1448 home->proto = IPPROTO_UDP;
1449+ home->require_ma = main_config.require_ma;
1450+
1451+ require_message_authenticator = false;
1452
1453 /*
1454 * Parse the configuration into the home server
1455@@ -647,6 +653,10 @@ home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SE
1456 */
1457 if (cf_section_parse(cs, home, home_server_config) < 0) goto error;
1458
1459+ if (fr_bool_auto_parse(cf_pair_find(cs, "require_message_authenticator"), &home->require_ma, require_message_authenticator) < 0) {
1460+ goto error;
1461+ }
1462+
1463 /*
1464 * It has an IP address, it must be a remote server.
1465 */
1466@@ -924,6 +934,7 @@ home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SE
1467 * Parse the SSL client configuration.
1468 */
1469 if (tls) {
1470+ home->require_ma = false;
1471 home->tls = tls_client_conf_parse(tls);
1472 if (!home->tls) {
1473 goto error;
1474diff --git a/src/main/tls_listen.c b/src/main/tls_listen.c
1475index 0eed87b64f..4ae3c5b975 100644
1476--- a/src/main/tls_listen.c
1477+++ b/src/main/tls_listen.c
1478@@ -299,6 +299,8 @@ get_application_data:
1479 packet->vps = NULL;
1480 PTHREAD_MUTEX_UNLOCK(&sock->mutex);
1481
1482+ packet->tls = true;
1483+
1484 if (!rad_packet_ok(packet, 0, NULL)) {
1485 if (DEBUG_ENABLED) ERROR("Receive - %s", fr_strerror());
1486 DEBUG("Closing TLS socket from client");
1487@@ -713,6 +715,8 @@ int proxy_tls_recv(rad_listen_t *listener)
1488 memcpy(packet->data, data, packet->data_len);
1489 memcpy(packet->vector, packet->data + 4, 16);
1490
1491+ packet->tls = true;
1492+
1493 /*
1494 * FIXME: Client MIB updates?
1495 */
1496@@ -765,6 +769,7 @@ int proxy_tls_send(rad_listen_t *listener, REQUEST *request)
1497 * if there's no packet, encode it here.
1498 */
1499 if (!request->proxy->data) {
1500+ request->reply->tls = true;
1501 request->proxy_listener->encode(request->proxy_listener,
1502 request);
1503 }
1504--
15052.35.7
1506
diff --git a/meta-networking/recipes-connectivity/freeradius/freeradius_3.0.21.bb b/meta-networking/recipes-connectivity/freeradius/freeradius_3.0.21.bb
index db37f65918..01d23fdf83 100644
--- a/meta-networking/recipes-connectivity/freeradius/freeradius_3.0.21.bb
+++ b/meta-networking/recipes-connectivity/freeradius/freeradius_3.0.21.bb
@@ -35,6 +35,7 @@ SRC_URI = "git://github.com/FreeRADIUS/freeradius-server.git;branch=v3.0.x;lfs=0
35 file://0001-version.c-don-t-print-build-flags.patch \ 35 file://0001-version.c-don-t-print-build-flags.patch \
36 file://CVE-2022-41860.patch \ 36 file://CVE-2022-41860.patch \
37 file://CVE-2022-41861.patch \ 37 file://CVE-2022-41861.patch \
38 file://CVE-2024-3596.patch \
38" 39"
39 40
40raddbdir="${sysconfdir}/${MLPREFIX}raddb" 41raddbdir="${sysconfdir}/${MLPREFIX}raddb"