Fix CVE-2024-3596
This commit is contained in:
parent
9c1891827b
commit
e2e00d8f89
765
CVE-2024-3596.patch
Normal file
765
CVE-2024-3596.patch
Normal file
@ -0,0 +1,765 @@
|
||||
Refer:
|
||||
https://build.opensuse.org/projects/SUSE:SLE-15-SP4:Update/packages/freeradius-server/files/CVE-2024-3596.patch?expand=1
|
||||
https://github.com/FreeRADIUS/freeradius-server/commit/7d095e85531d4941b43c0ad6d5c880291625a585
|
||||
|
||||
diff -Nur freeradius-server-3.2.3_bak/man/man1/radclient.1 freeradius-server-3.2.3/man/man1/radclient.1
|
||||
--- freeradius-server-3.2.3_bak/man/man1/radclient.1 2024-07-16 16:46:31.231616649 +0800
|
||||
+++ freeradius-server-3.2.3/man/man1/radclient.1 2024-07-16 16:46:48.236642156 +0800
|
||||
@@ -5,6 +5,7 @@
|
||||
.B radclient
|
||||
.RB [ \-4 ]
|
||||
.RB [ \-6 ]
|
||||
+.RB [ \-b ]
|
||||
.RB [ \-c
|
||||
.IR count ]
|
||||
.RB [ \-d
|
||||
@@ -52,6 +53,13 @@
|
||||
Use IPv4 (default)
|
||||
.IP \-6
|
||||
Use IPv6
|
||||
+.IP \-b
|
||||
+Enforce the Blast RADIUS checks. All replies to an Access-Request packet
|
||||
+must contain a Message-Authenticator as the first attribute.
|
||||
+
|
||||
+For compatibility with old servers, this flag is not set by default.
|
||||
+However, radclient still checks for the Blast RADIUS signature, and
|
||||
+discards packets which match the attack.
|
||||
.IP \-c\ \fIcount\fP
|
||||
Send each packet \fIcount\fP times.
|
||||
.IP \-d\ \fIraddb_directory\fP
|
||||
diff -Nur freeradius-server-3.2.3_bak/raddb/clients.conf freeradius-server-3.2.3/raddb/clients.conf
|
||||
--- freeradius-server-3.2.3_bak/raddb/clients.conf 2024-07-16 16:46:31.233616652 +0800
|
||||
+++ freeradius-server-3.2.3/raddb/clients.conf 2024-07-16 16:46:48.236642156 +0800
|
||||
@@ -100,15 +100,30 @@
|
||||
secret = testing123
|
||||
|
||||
#
|
||||
- # Old-style clients do not send a Message-Authenticator
|
||||
- # in an Access-Request. RFC 5080 suggests that all clients
|
||||
- # SHOULD include it in an Access-Request. The configuration
|
||||
- # item below allows the server to require it. If a client
|
||||
- # is required to include a Message-Authenticator and it does
|
||||
- # not, then the packet will be silently discarded.
|
||||
+ # The global configuration "security.require_message_authenticator"
|
||||
+ # flag sets the default for all clients. That default can be
|
||||
+ # over-ridden here, by setting it to "no".
|
||||
+ #
|
||||
+ # This flag exists solely for legacy clients which do not send
|
||||
+ # Message-Authenticator in all Access-Request packets. We do not
|
||||
+ # recommend setting it to "no".
|
||||
+ #
|
||||
+ # allowed values: yes, no
|
||||
+ #
|
||||
+# require_message_authenticator = yes
|
||||
+
|
||||
+ #
|
||||
+ # The global configuration "security.limit_proxy_state"
|
||||
+ # flag sets the default for all clients. That default can be
|
||||
+ # over-ridden here, by setting it to "no".
|
||||
+ #
|
||||
+ # This flag exists solely for legacy clients which do not send
|
||||
+ # Message-Authenticator in all Access-Request packets. We do not
|
||||
+ # recommend setting it to "no".
|
||||
#
|
||||
# allowed values: yes, no
|
||||
- require_message_authenticator = no
|
||||
+ #
|
||||
+# limit_proxy_state = yes
|
||||
|
||||
#
|
||||
# The short name is used as an alias for the fully qualified
|
||||
diff -Nur freeradius-server-3.2.3_bak/raddb/proxy.conf freeradius-server-3.2.3/raddb/proxy.conf
|
||||
--- freeradius-server-3.2.3_bak/raddb/proxy.conf 2024-07-16 16:46:31.242616665 +0800
|
||||
+++ freeradius-server-3.2.3/raddb/proxy.conf 2024-07-16 16:46:48.237642158 +0800
|
||||
@@ -252,6 +252,20 @@
|
||||
#
|
||||
secret = testing123
|
||||
|
||||
+ # The global configuration "security.require_message_authenticator"
|
||||
+ # flag sets the default for all home servers. That default can be
|
||||
+ # over-ridden here, by setting it to "no".
|
||||
+ #
|
||||
+ # This flag exists solely for legacy home servers which do
|
||||
+ # not send Message-Authenticator in all Access-Accept,
|
||||
+ # Access-Reject, or Access-Challenge packets. We do not
|
||||
+ # recommend setting it to "no".
|
||||
+ #
|
||||
+ # allowed values: yes, no
|
||||
+ #
|
||||
+ #require_message_authenticator = no
|
||||
+
|
||||
+
|
||||
############################################################
|
||||
#
|
||||
# The rest of the configuration items listed here are optional,
|
||||
diff -Nur freeradius-server-3.2.3_bak/raddb/radiusd.conf.in freeradius-server-3.2.3/raddb/radiusd.conf.in
|
||||
--- freeradius-server-3.2.3_bak/raddb/radiusd.conf.in 2024-07-16 16:46:31.242616665 +0800
|
||||
+++ freeradius-server-3.2.3/raddb/radiusd.conf.in 2024-07-16 16:46:48.237642158 +0800
|
||||
@@ -572,6 +572,64 @@
|
||||
#
|
||||
status_server = yes
|
||||
|
||||
+ #
|
||||
+ # Global configuration for requiring Message-Authenticator
|
||||
+ # in all Access-* packets sent over UDP or TCP. This flag
|
||||
+ # is ignored for TLS.
|
||||
+
|
||||
+ #
|
||||
+ # This flag sets the global default for all clients and home
|
||||
+ # servers. It can be over-ridden in an individual client or
|
||||
+ # home server definition by adding a flag to that section:
|
||||
+ #
|
||||
+ # require_message_authenticator = no
|
||||
+ #
|
||||
+ # If the server produces error message which says "Packet
|
||||
+ # does not contain required Message-Authenticator attribute",
|
||||
+ # then this configuration item has to be updated.
|
||||
+ #
|
||||
+ # WARNING: This item should always be left as "yes",
|
||||
+ # otherwise it is possible for MITM attackers to create fake
|
||||
+ # Access-Accept packets to the NAS!
|
||||
+ #
|
||||
+ require_message_authenticator = yes
|
||||
+
|
||||
+ #
|
||||
+ # Global configuration for requiring Message-Authenticator
|
||||
+ # Access-Request packets from a NAS, but only if those
|
||||
+ # packets also contain Proxy-State. This flag only applies
|
||||
+ # to packets sent over UDP or TCP. This flag is ignored for
|
||||
+ # TLS.
|
||||
+ #
|
||||
+ # This flag sets the global default for all clients. It can
|
||||
+ # be over-ridden in an individual client definition by adding
|
||||
+ # a flag to that section:
|
||||
+ #
|
||||
+ # limit_proxy_state = no
|
||||
+ #
|
||||
+ # If "require_message_authenticator" is set to "yes", this
|
||||
+ # configuration item is ignored.
|
||||
+ #
|
||||
+ # If "require_message_authenticator" is set to "no", this
|
||||
+ # configuration item is checked.
|
||||
+ #
|
||||
+ # This configuration item should ALWAYS be set to "yes".
|
||||
+ #
|
||||
+ # The only reason to set it to "no" is when the client is a
|
||||
+ # proxy, AND the proxy does not send Message-Authenticator in
|
||||
+ # Access-Request packets. Even then, the best approach to
|
||||
+ # fix the issue is to (1) update the proxy to send
|
||||
+ # Message-Authenticator, and if that can't be done, then (2)
|
||||
+ # set this flag to "no", but ONLY on a per-client basis.
|
||||
+ #
|
||||
+ # WARNING: Setting both this flag and the
|
||||
+ # "require_message_authenticator" flag to "no" will allow
|
||||
+ # MITM attackers to create fake Access-Accept packets to the
|
||||
+ # NAS! At least one of them MUST be set to "yes" for the
|
||||
+ # system to have any protection against the attack.
|
||||
+ #
|
||||
+ limit_proxy_state = yes
|
||||
+
|
||||
@openssl_version_check_config@
|
||||
}
|
||||
|
||||
diff -Nur freeradius-server-3.2.3_bak/src/include/clients.h freeradius-server-3.2.3/src/include/clients.h
|
||||
--- freeradius-server-3.2.3_bak/src/include/clients.h 2024-07-16 16:46:31.259616690 +0800
|
||||
+++ freeradius-server-3.2.3/src/include/clients.h 2024-07-16 16:46:48.237642158 +0800
|
||||
@@ -43,7 +43,9 @@
|
||||
|
||||
char const *secret; //!< Secret PSK.
|
||||
|
||||
- bool message_authenticator; //!< Require RADIUS message authenticator in requests.
|
||||
+ bool require_ma; //!< Require RADIUS message authenticator in requests.
|
||||
+
|
||||
+ bool limit_proxy_state; //!< Limit Proxy-State in requests
|
||||
|
||||
char const *nas_type; //!< Type of client (arbitrary).
|
||||
|
||||
diff -Nur freeradius-server-3.2.3_bak/src/include/conffile.h freeradius-server-3.2.3/src/include/conffile.h
|
||||
--- freeradius-server-3.2.3_bak/src/include/conffile.h 2024-07-16 16:46:31.259616690 +0800
|
||||
+++ freeradius-server-3.2.3/src/include/conffile.h 2024-07-16 16:46:48.238642159 +0800
|
||||
@@ -140,6 +140,7 @@
|
||||
#define PW_TYPE_MULTI (1 << 18) //!< CONF_PAIR can have multiple copies.
|
||||
#define PW_TYPE_NOT_EMPTY (1 << 19) //!< CONF_PAIR is required to have a non zero length value.
|
||||
#define PW_TYPE_FILE_EXISTS ((1 << 20) | PW_TYPE_STRING) //!< File matching value must exist
|
||||
+#define PW_TYPE_IGNORE_DEFAULT (1 << 21) //!< don't set from .dflt if the CONF_PAIR is missing
|
||||
/* @} **/
|
||||
|
||||
#define FR_INTEGER_COND_CHECK(_name, _var, _cond, _new)\
|
||||
diff -Nur freeradius-server-3.2.3_bak/src/include/libradius.h freeradius-server-3.2.3/src/include/libradius.h
|
||||
--- freeradius-server-3.2.3_bak/src/include/libradius.h 2024-07-16 16:46:31.259616690 +0800
|
||||
+++ freeradius-server-3.2.3/src/include/libradius.h 2024-07-16 16:46:48.238642159 +0800
|
||||
@@ -410,6 +410,7 @@
|
||||
#ifdef WITH_RADIUSV11
|
||||
bool radiusv11;
|
||||
#endif
|
||||
+ bool tls; //!< uses secure transport
|
||||
} RADIUS_PACKET;
|
||||
|
||||
typedef enum {
|
||||
@@ -527,6 +528,11 @@
|
||||
/* radius.c */
|
||||
int rad_send(RADIUS_PACKET *, RADIUS_PACKET const *, char const *secret);
|
||||
bool rad_packet_ok(RADIUS_PACKET *packet, int flags, decode_fail_t *reason);
|
||||
+/*
|
||||
+ * 1 == require_ma
|
||||
+ * 2 == msg_peek
|
||||
+ * 3 == limit_proxy_state
|
||||
+ */
|
||||
RADIUS_PACKET *rad_recv(TALLOC_CTX *ctx, int fd, int flags);
|
||||
ssize_t rad_recv_header(int sockfd, fr_ipaddr_t *src_ipaddr, uint16_t *src_port, int *code);
|
||||
void rad_recv_discard(int sockfd);
|
||||
diff -Nur freeradius-server-3.2.3_bak/src/include/radiusd.h freeradius-server-3.2.3/src/include/radiusd.h
|
||||
--- freeradius-server-3.2.3_bak/src/include/radiusd.h 2024-07-16 16:46:31.260616692 +0800
|
||||
+++ freeradius-server-3.2.3/src/include/radiusd.h 2024-07-16 16:46:48.239642161 +0800
|
||||
@@ -174,6 +174,9 @@
|
||||
|
||||
bool exiting; //!< are we exiting?
|
||||
|
||||
+ bool require_ma; //!< global configuration for all clients and home servers
|
||||
+
|
||||
+ bool limit_proxy_state; //!< global configuration for all clients
|
||||
|
||||
#ifdef ENABLE_OPENSSL_VERSION_CHECK
|
||||
char const *allow_vulnerable_openssl; //!< The CVE number of the last security issue acknowledged.
|
||||
diff -Nur freeradius-server-3.2.3_bak/src/include/realms.h freeradius-server-3.2.3/src/include/realms.h
|
||||
--- freeradius-server-3.2.3_bak/src/include/realms.h 2024-07-16 16:46:31.260616692 +0800
|
||||
+++ freeradius-server-3.2.3/src/include/realms.h 2024-07-16 16:46:48.239642161 +0800
|
||||
@@ -69,6 +69,7 @@
|
||||
bool dual; //!< One of a pair of homeservers on consecutive ports.
|
||||
bool dynamic; //!< is this a dynamically added home server?
|
||||
bool nonblock; //!< Enable a socket non-blocking to the home server.
|
||||
+ bool require_ma; //!< for all replies to Access-Request and Status-Server
|
||||
#ifdef WITH_COA_TUNNEL
|
||||
bool recv_coa; //!< receive CoA packets, too
|
||||
#endif
|
||||
diff -Nur freeradius-server-3.2.3_bak/src/lib/radius.c freeradius-server-3.2.3/src/lib/radius.c
|
||||
--- freeradius-server-3.2.3_bak/src/lib/radius.c 2024-07-16 16:46:31.262616695 +0800
|
||||
+++ freeradius-server-3.2.3/src/lib/radius.c 2024-07-16 16:46:48.240642163 +0800
|
||||
@@ -1831,6 +1831,7 @@
|
||||
uint16_t total_length;
|
||||
int len;
|
||||
VALUE_PAIR const *reply;
|
||||
+ bool seen_ma = false;
|
||||
|
||||
/*
|
||||
* A 4K packet, aligned on 64-bits.
|
||||
@@ -1909,6 +1910,27 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
+ * Always add Message-Authenticator for replies to
|
||||
+ * Access-Request packets.
|
||||
+ *
|
||||
+ * It must be the FIRST attribute in the packet.
|
||||
+ */
|
||||
+ if (!packet->tls &&
|
||||
+ ((original && (original->code == PW_CODE_ACCESS_REQUEST)) ||
|
||||
+ (packet->code == PW_CODE_ACCESS_REQUEST))) {
|
||||
+ seen_ma = true;
|
||||
+
|
||||
+ packet->offset = RADIUS_HDR_LEN;
|
||||
+
|
||||
+ ptr[0] = PW_MESSAGE_AUTHENTICATOR;
|
||||
+ ptr[1] = 18;
|
||||
+ memset(ptr + 2, 0, 16);
|
||||
+
|
||||
+ ptr += 18;
|
||||
+ total_length += 18;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
* Loop over the reply attributes for the packet.
|
||||
*/
|
||||
reply = packet->vps;
|
||||
@@ -1984,15 +2006,13 @@
|
||||
* length and initial value.
|
||||
*/
|
||||
if (!reply->da->vendor && (reply->da->attr == PW_MESSAGE_AUTHENTICATOR)) {
|
||||
-#ifdef WITH_RADIUSV11
|
||||
/*
|
||||
- * RADIUSV11 does not encode or verify Message-Authenticator.
|
||||
+ * We have already encoded the Message-Authenticator, don't do it again.
|
||||
*/
|
||||
- if (packet->radiusv11) {
|
||||
+ if (seen_ma) {
|
||||
reply = reply->next;
|
||||
continue;
|
||||
}
|
||||
-#endif
|
||||
|
||||
if (room < 18) break;
|
||||
|
||||
@@ -2510,6 +2530,8 @@
|
||||
char host_ipaddr[128];
|
||||
#ifndef WITH_RADIUSV11_ONLY
|
||||
bool require_ma = false;
|
||||
+ bool limit_proxy_state = false;
|
||||
+ bool seen_proxy_state = false;
|
||||
bool seen_ma = false;
|
||||
bool eap = false;
|
||||
bool non_eap = false;
|
||||
@@ -2561,13 +2583,14 @@
|
||||
/*
|
||||
* Message-Authenticator is required in Status-Server
|
||||
* packets, otherwise they can be trivially forged.
|
||||
- */
|
||||
- if (hdr->code == PW_CODE_STATUS_SERVER) require_ma = true;
|
||||
-
|
||||
- /*
|
||||
+ *
|
||||
* It's also required if the caller asks for it.
|
||||
+ *
|
||||
+ * We only limit Proxy-State if we're not requiring
|
||||
+ * Message-Authenticator.
|
||||
*/
|
||||
- if (flags) require_ma = true;
|
||||
+ require_ma = ((flags & 0x01) != 0) || (hdr->code == PW_CODE_STATUS_SERVER);
|
||||
+ limit_proxy_state = ((flags & 0x04) != 0) & !require_ma;
|
||||
|
||||
/*
|
||||
* Repeat the length checks. This time, instead of
|
||||
@@ -2731,6 +2754,10 @@
|
||||
non_eap = true;
|
||||
break;
|
||||
|
||||
+ case PW_PROXY_STATE:
|
||||
+ seen_proxy_state = true;
|
||||
+ break;
|
||||
+
|
||||
case PW_MESSAGE_AUTHENTICATOR:
|
||||
#ifdef WITH_RADIUSV11
|
||||
/*
|
||||
@@ -2817,6 +2844,18 @@
|
||||
inet_ntop(packet->src_ipaddr.af,
|
||||
&packet->src_ipaddr.ipaddr,
|
||||
host_ipaddr, sizeof(host_ipaddr)));
|
||||
+ failure = DECODE_FAIL_MA_MISSING;
|
||||
+ goto finish;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * The client is a NAS which shouldn't send Proxy-State, but it did!
|
||||
+ */
|
||||
+ if (limit_proxy_state && seen_proxy_state && !seen_ma) {
|
||||
+ 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",
|
||||
+ inet_ntop(packet->src_ipaddr.af,
|
||||
+ &packet->src_ipaddr.ipaddr,
|
||||
+ host_ipaddr, sizeof(host_ipaddr)));
|
||||
failure = DECODE_FAIL_MA_MISSING;
|
||||
goto finish;
|
||||
}
|
||||
diff -Nur freeradius-server-3.2.3_bak/src/main/client.c freeradius-server-3.2.3/src/main/client.c
|
||||
--- freeradius-server-3.2.3_bak/src/main/client.c 2024-07-16 16:46:31.263616696 +0800
|
||||
+++ freeradius-server-3.2.3/src/main/client.c 2024-07-16 16:46:48.241642164 +0800
|
||||
@@ -328,7 +328,8 @@
|
||||
(old->coa_home_server == client->coa_home_server) &&
|
||||
(old->coa_home_pool == client->coa_home_pool) &&
|
||||
#endif
|
||||
- (old->message_authenticator == client->message_authenticator)) {
|
||||
+ (old->require_ma == client->require_ma) &&
|
||||
+ (old->limit_proxy_state == client->limit_proxy_state)) {
|
||||
WARN("Ignoring duplicate client %s", client->longname);
|
||||
client_free(client);
|
||||
return true;
|
||||
@@ -512,7 +513,8 @@
|
||||
|
||||
{ "src_ipaddr", FR_CONF_POINTER(PW_TYPE_STRING, &cl_srcipaddr), NULL },
|
||||
|
||||
- { "require_message_authenticator", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, RADCLIENT, message_authenticator), "no" },
|
||||
+ { "require_message_authenticator", FR_CONF_OFFSET(PW_TYPE_BOOLEAN | PW_TYPE_IGNORE_DEFAULT, RADCLIENT, require_ma), NULL },
|
||||
+ { "limit_proxy_state", FR_CONF_OFFSET(PW_TYPE_BOOLEAN | PW_TYPE_IGNORE_DEFAULT, RADCLIENT, limit_proxy_state), NULL },
|
||||
|
||||
{ "secret", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_SECRET, RADCLIENT, secret), NULL },
|
||||
{ "shortname", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, shortname), NULL },
|
||||
@@ -724,7 +726,7 @@
|
||||
{ "FreeRADIUS-Client-Src-IP-Address", FR_CONF_OFFSET(PW_TYPE_IPV4_ADDR, RADCLIENT, src_ipaddr), NULL },
|
||||
{ "FreeRADIUS-Client-Src-IPv6-Address", FR_CONF_OFFSET(PW_TYPE_IPV6_ADDR, RADCLIENT, src_ipaddr), NULL },
|
||||
|
||||
- { "FreeRADIUS-Client-Require-MA", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, RADCLIENT, message_authenticator), NULL },
|
||||
+ { "FreeRADIUS-Client-Require-MA", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, RADCLIENT, require_ma), NULL },
|
||||
|
||||
{ "FreeRADIUS-Client-Secret", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, secret), "" },
|
||||
{ "FreeRADIUS-Client-Shortname", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, shortname), "" },
|
||||
@@ -906,6 +908,15 @@
|
||||
c = talloc_zero(ctx, RADCLIENT);
|
||||
c->cs = cs;
|
||||
|
||||
+ /*
|
||||
+ * Set the "require message authenticator" and "limit
|
||||
+ * proxy state" flags from the global default. If the
|
||||
+ * configuration item exists, AND is set, it will
|
||||
+ * over-ride the flag.
|
||||
+ */
|
||||
+ c->require_ma = main_config.require_ma;
|
||||
+ c->limit_proxy_state = main_config.limit_proxy_state;
|
||||
+
|
||||
memset(&cl_ipaddr, 0, sizeof(cl_ipaddr));
|
||||
cl_netmask = 255;
|
||||
|
||||
@@ -1233,7 +1244,7 @@
|
||||
if (shortname) c->shortname = talloc_typed_strdup(c, shortname);
|
||||
if (type) c->nas_type = talloc_typed_strdup(c, type);
|
||||
if (server) c->server = talloc_typed_strdup(c, server);
|
||||
- c->message_authenticator = require_ma;
|
||||
+ c->require_ma = require_ma;
|
||||
|
||||
return c;
|
||||
}
|
||||
diff -Nur freeradius-server-3.2.3_bak/src/main/conffile.c freeradius-server-3.2.3/src/main/conffile.c
|
||||
--- freeradius-server-3.2.3_bak/src/main/conffile.c 2024-07-16 16:46:31.263616696 +0800
|
||||
+++ freeradius-server-3.2.3/src/main/conffile.c 2024-07-16 16:46:48.242642166 +0800
|
||||
@@ -1424,6 +1424,7 @@
|
||||
{
|
||||
int rcode;
|
||||
bool deprecated, required, attribute, secret, file_input, cant_be_empty, tmpl, multi, file_exists;
|
||||
+ bool ignore_dflt;
|
||||
char **q;
|
||||
char const *value;
|
||||
CONF_PAIR *cp = NULL;
|
||||
@@ -1447,6 +1448,7 @@
|
||||
cant_be_empty = (type & PW_TYPE_NOT_EMPTY);
|
||||
tmpl = (type & PW_TYPE_TMPL);
|
||||
multi = (type & PW_TYPE_MULTI);
|
||||
+ ignore_dflt = (type & PW_TYPE_IGNORE_DEFAULT);
|
||||
|
||||
if (attribute) required = true;
|
||||
if (required) cant_be_empty = true; /* May want to review this in the future... */
|
||||
@@ -1470,7 +1472,7 @@
|
||||
* section, use the default value.
|
||||
*/
|
||||
if (!cp) {
|
||||
- if (deprecated) return 0; /* Don't set the default value */
|
||||
+ if (deprecated || ignore_dflt) return 0; /* Don't set the default value */
|
||||
|
||||
rcode = 1;
|
||||
value = dflt;
|
||||
diff -Nur freeradius-server-3.2.3_bak/src/main/listen.c freeradius-server-3.2.3/src/main/listen.c
|
||||
--- freeradius-server-3.2.3_bak/src/main/listen.c 2024-07-16 16:46:31.263616696 +0800
|
||||
+++ freeradius-server-3.2.3/src/main/listen.c 2024-07-16 16:46:48.243642167 +0800
|
||||
@@ -1947,7 +1947,7 @@
|
||||
* Now that we've sanity checked everything, receive the
|
||||
* packet.
|
||||
*/
|
||||
- packet = rad_recv(ctx, listener->fd, client->message_authenticator);
|
||||
+ packet = rad_recv(ctx, listener->fd, client->require_ma | (((int) client->limit_proxy_state) << 2));
|
||||
if (!packet) {
|
||||
FR_STATS_INC(auth, total_malformed_requests);
|
||||
if (DEBUG_ENABLED) ERROR("Receive - %s", fr_strerror());
|
||||
@@ -2343,7 +2343,7 @@
|
||||
* Now that we've sanity checked everything, receive the
|
||||
* packet.
|
||||
*/
|
||||
- packet = rad_recv(ctx, listener->fd, client->message_authenticator);
|
||||
+ packet = rad_recv(ctx, listener->fd, client->require_ma);
|
||||
if (!packet) {
|
||||
FR_STATS_INC(coa, total_malformed_requests);
|
||||
if (DEBUG_ENABLED) ERROR("Receive - %s", fr_strerror());
|
||||
diff -Nur freeradius-server-3.2.3_bak/src/main/mainconfig.c freeradius-server-3.2.3/src/main/mainconfig.c
|
||||
--- freeradius-server-3.2.3_bak/src/main/mainconfig.c 2024-07-16 16:46:31.264616698 +0800
|
||||
+++ freeradius-server-3.2.3/src/main/mainconfig.c 2024-07-16 16:46:48.243642167 +0800
|
||||
@@ -160,6 +160,8 @@
|
||||
{ "max_attributes", FR_CONF_POINTER(PW_TYPE_INTEGER, &fr_max_attributes), STRINGIFY(0) },
|
||||
{ "reject_delay", FR_CONF_POINTER(PW_TYPE_TIMEVAL, &main_config.reject_delay), STRINGIFY(0) },
|
||||
{ "status_server", FR_CONF_POINTER(PW_TYPE_BOOLEAN, &main_config.status_server), "no"},
|
||||
+ { "require_message_authenticator", FR_CONF_POINTER(PW_TYPE_BOOLEAN, &main_config.require_ma), "yes"},
|
||||
+ { "limit_proxy_state", FR_CONF_POINTER(PW_TYPE_BOOLEAN, &main_config.limit_proxy_state), "yes"},
|
||||
#ifdef ENABLE_OPENSSL_VERSION_CHECK
|
||||
{ "allow_vulnerable_openssl", FR_CONF_POINTER(PW_TYPE_STRING, &main_config.allow_vulnerable_openssl), "no"},
|
||||
#endif
|
||||
diff -Nur freeradius-server-3.2.3_bak/src/main/process.c freeradius-server-3.2.3/src/main/process.c
|
||||
--- freeradius-server-3.2.3_bak/src/main/process.c 2024-07-16 16:46:31.264616698 +0800
|
||||
+++ freeradius-server-3.2.3/src/main/process.c 2024-07-16 16:46:48.244642169 +0800
|
||||
@@ -2790,11 +2790,25 @@
|
||||
* server core, but I guess we can fix that later.
|
||||
*/
|
||||
if (!request->proxy_reply) {
|
||||
+ decode_fail_t reason;
|
||||
+
|
||||
+ /*
|
||||
+ * If the home server configuration requires a Message-Authenticator, then set the flag,
|
||||
+ * but only if the proxied packet is Access-Request or Status-Sercer.
|
||||
+ *
|
||||
+ * The realms.c file already clears require_ma for TLS connections.
|
||||
+ */
|
||||
+ bool require_ma = request->home_server->require_ma && (request->proxy->code == PW_CODE_ACCESS_REQUEST);
|
||||
if (!request->home_server) {
|
||||
proxy_reply_too_late(request);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+ if (!rad_packet_ok(packet, require_ma, &reason)) {
|
||||
+ DEBUG("Ignoring invalid packet - %s", fr_strerror());
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
if (rad_verify(packet, request->proxy,
|
||||
request->home_server->secret) != 0) {
|
||||
DEBUG("Ignoring spoofed proxy reply. Signature is invalid");
|
||||
diff -Nur freeradius-server-3.2.3_bak/src/main/radclient.c freeradius-server-3.2.3/src/main/radclient.c
|
||||
--- freeradius-server-3.2.3_bak/src/main/radclient.c 2024-07-16 16:46:31.264616698 +0800
|
||||
+++ freeradius-server-3.2.3/src/main/radclient.c 2024-07-16 16:46:48.245642170 +0800
|
||||
@@ -60,6 +60,7 @@
|
||||
static int resend_count = 1;
|
||||
static bool done = true;
|
||||
static bool print_filename = false;
|
||||
+static bool blast_radius = false;
|
||||
|
||||
static fr_ipaddr_t client_ipaddr;
|
||||
static uint16_t client_port = 0;
|
||||
@@ -95,6 +96,7 @@
|
||||
fprintf(stderr, " <command> One of auth, acct, status, coa, disconnect or auto.\n");
|
||||
fprintf(stderr, " -4 Use IPv4 address of server\n");
|
||||
fprintf(stderr, " -6 Use IPv6 address of server.\n");
|
||||
+ fprintf(stderr, " -b Mandate checks for Blast RADIUS issue (this is not set by default).\n");
|
||||
fprintf(stderr, " -c <count> Send each packet 'count' times.\n");
|
||||
fprintf(stderr, " -d <raddb> Set user dictionary directory (defaults to " RADDBDIR ").\n");
|
||||
fprintf(stderr, " -D <dictdir> Set main dictionary directory (defaults to " DICTDIR ").\n");
|
||||
@@ -1060,6 +1062,131 @@
|
||||
}
|
||||
|
||||
/*
|
||||
+ * Do Blast RADIUS checks.
|
||||
+ *
|
||||
+ * The request is an Access-Request, and does NOT contain Proxy-State.
|
||||
+ *
|
||||
+ * The reply is a raw packet, and is NOT yet decoded.
|
||||
+ */
|
||||
+static int blast_radius_check(rc_request_t *request, RADIUS_PACKET *reply)
|
||||
+{
|
||||
+ uint8_t *attr, *end;
|
||||
+ VALUE_PAIR *vp;
|
||||
+ bool have_message_authenticator = false;
|
||||
+
|
||||
+ /*
|
||||
+ * We've received a raw packet. Nothing has (as of yet) checked
|
||||
+ * anything in it other than the length, and that it's a
|
||||
+ * well-formed RADIUS packet.
|
||||
+ */
|
||||
+ switch (reply->data[0]) {
|
||||
+ case PW_CODE_ACCESS_ACCEPT:
|
||||
+ case PW_CODE_ACCESS_REJECT:
|
||||
+ case PW_CODE_ACCESS_CHALLENGE:
|
||||
+ if (reply->data[1] != request->packet->id) {
|
||||
+ ERROR("Invalid reply ID %d to Access-Request ID %d", reply->data[1], request->packet->id);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ ERROR("Invalid reply code %d to Access-Request", reply->data[0]);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * If the reply has a Message-Authenticator, then it MIGHT be fine.
|
||||
+ */
|
||||
+ attr = reply->data + 20;
|
||||
+ end = reply->data + reply->data_len;
|
||||
+
|
||||
+ /*
|
||||
+ * It should be the first attribute, so we warn if it isn't there.
|
||||
+ *
|
||||
+ * But it's not a fatal error.
|
||||
+ */
|
||||
+ if (blast_radius && (attr[0] != PW_MESSAGE_AUTHENTICATOR)) {
|
||||
+ RDEBUG("WARNING The %s reply packet does not have Message-Authenticator as the first attribute. The packet may be vulnerable to Blast RADIUS attacks.",
|
||||
+ fr_packet_codes[reply->data[0]]);
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Set up for Proxy-State checks.
|
||||
+ *
|
||||
+ * If we see a Proxy-State in the reply which we didn't send, then it's a Blast RADIUS attack.
|
||||
+ */
|
||||
+ vp = fr_pair_find_by_num(request->packet->vps, PW_PROXY_STATE, 0, TAG_ANY);
|
||||
+
|
||||
+ while (attr < end) {
|
||||
+ /*
|
||||
+ * Blast RADIUS work-arounds require that
|
||||
+ * Message-Authenticator is the first attribute in the
|
||||
+ * reply. Note that we don't check for it being the
|
||||
+ * first attribute, but simply that it exists.
|
||||
+ *
|
||||
+ * That check is a balance between securing the reply
|
||||
+ * packet from attacks, and not violating the RFCs which
|
||||
+ * say that there is no order to attributes in the
|
||||
+ * packet.
|
||||
+ *
|
||||
+ * However, no matter the status of the '-b' flag we
|
||||
+ * still can check for the signature of the attack, and
|
||||
+ * discard packets which are suspicious. This behavior
|
||||
+ * protects radclient from the attack, without mandating
|
||||
+ * new behavior on the server side.
|
||||
+ *
|
||||
+ * Note that we don't set the '-b' flag by default.
|
||||
+ * radclient is intended for testing / debugging, and is
|
||||
+ * not intended to be used as part of a secure login /
|
||||
+ * user checking system.
|
||||
+ */
|
||||
+ if (attr[0] == PW_MESSAGE_AUTHENTICATOR) {
|
||||
+ have_message_authenticator = true;
|
||||
+ goto next;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * If there are Proxy-State attributes in the reply, they must
|
||||
+ * match EXACTLY the Proxy-State attributes in the request.
|
||||
+ *
|
||||
+ * Note that we don't care if there are more Proxy-States
|
||||
+ * in the request than in the reply. The Blast RADIUS
|
||||
+ * issue requires _adding_ Proxy-State attributes, and
|
||||
+ * cannot work when the server _deletes_ Proxy-State
|
||||
+ * attributes.
|
||||
+ */
|
||||
+ if (attr[0] == PW_PROXY_STATE) {
|
||||
+ if (!vp || (vp->length != (size_t) (attr[1] - 2)) || (memcmp(vp->vp_octets, attr + 2, vp->length) != 0)) {
|
||||
+ ERROR("Invalid reply to Access-Request ID %d - Discarding packet due to Blast RADIUS attack being detected.", request->packet->id);
|
||||
+ ERROR("We received a Proxy-State in the reply which we did not send, or which is different from what we sent.");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ vp = fr_pair_find_by_num(vp->next, PW_PROXY_STATE, 0, TAG_ANY);
|
||||
+ }
|
||||
+
|
||||
+ next:
|
||||
+ attr += attr[1];
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * If "-b" is set, then we require Message-Authenticator in the reply.
|
||||
+ */
|
||||
+ if (blast_radius && !have_message_authenticator) {
|
||||
+ ERROR("The %s reply packet does not contain Message-Authenticator - discarding packet due to Blast RADIUS checks.",
|
||||
+ fr_packet_codes[reply->data[0]]);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * The packet doesn't look like it's a Blast RADIUS attack. The
|
||||
+ * caller will now verify the packet signature.
|
||||
+ */
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
* Receive one packet, maybe.
|
||||
*/
|
||||
static int recv_one_packet(int wait_time)
|
||||
@@ -1111,6 +1238,20 @@
|
||||
request = fr_packet2myptr(rc_request_t, packet, packet_p);
|
||||
|
||||
/*
|
||||
+ * We want radclient to be able to send any packet, including
|
||||
+ * imperfect ones. However, we do NOT want to be vulnerable to
|
||||
+ * the "Blast RADIUS" issue. Instead of adding command-line
|
||||
+ * flags to enable/disable similar flags to what the server
|
||||
+ * sends, we just do a few more smart checks to double-check
|
||||
+ * things.
|
||||
+ */
|
||||
+ if ((request->packet->code == PW_CODE_ACCESS_REQUEST) &&
|
||||
+ blast_radius_check(request, reply) < 0) {
|
||||
+ rad_free(&reply);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
* Fails the signature validation: not a real reply.
|
||||
* FIXME: Silently drop it and listen for another packet.
|
||||
*/
|
||||
@@ -1243,7 +1384,7 @@
|
||||
exit(1);
|
||||
}
|
||||
|
||||
- while ((c = getopt(argc, argv, "46c:d:D:f:Fhn:p:qr:sS:t:vx"
|
||||
+ while ((c = getopt(argc, argv, "46bc:d:D:f:Fhn:p:qr:sS:t:vx"
|
||||
#ifdef WITH_TCP
|
||||
"P:"
|
||||
#endif
|
||||
@@ -1256,6 +1397,10 @@
|
||||
force_af = AF_INET6;
|
||||
break;
|
||||
|
||||
+ case 'b':
|
||||
+ blast_radius = true;
|
||||
+ break;
|
||||
+
|
||||
case 'c':
|
||||
if (!isdigit((uint8_t) *optarg)) usage();
|
||||
|
||||
diff -Nur freeradius-server-3.2.3_bak/src/main/realms.c freeradius-server-3.2.3/src/main/realms.c
|
||||
--- freeradius-server-3.2.3_bak/src/main/realms.c 2024-07-16 16:46:31.265616699 +0800
|
||||
+++ freeradius-server-3.2.3/src/main/realms.c 2024-07-16 16:46:48.246642172 +0800
|
||||
@@ -477,6 +477,7 @@
|
||||
|
||||
static CONF_PARSER home_server_config[] = {
|
||||
{ "nonblock", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, home_server_t, nonblock), "no" },
|
||||
+ { "require_message_authenticator", FR_CONF_OFFSET(PW_TYPE_BOOLEAN | PW_TYPE_IGNORE_DEFAULT, home_server_t, require_ma), NULL },
|
||||
{ "ipaddr", FR_CONF_OFFSET(PW_TYPE_COMBO_IP_ADDR, home_server_t, ipaddr), NULL },
|
||||
{ "ipv4addr", FR_CONF_OFFSET(PW_TYPE_IPV4_ADDR, home_server_t, ipaddr), NULL },
|
||||
{ "ipv6addr", FR_CONF_OFFSET(PW_TYPE_IPV6_ADDR, home_server_t, ipaddr), NULL },
|
||||
@@ -780,6 +781,7 @@
|
||||
home->cs = cs;
|
||||
home->state = HOME_STATE_UNKNOWN;
|
||||
home->proto = IPPROTO_UDP;
|
||||
+ home->require_ma = main_config.require_ma;
|
||||
|
||||
/*
|
||||
* Parse the configuration into the home server
|
||||
@@ -1116,6 +1118,11 @@
|
||||
if (tls) {
|
||||
int rcode;
|
||||
|
||||
+ /*
|
||||
+ * We don't require this for TLS connections.
|
||||
+ */
|
||||
+ home->require_ma = false;
|
||||
+
|
||||
home->tls = tls_client_conf_parse(tls);
|
||||
if (!home->tls) {
|
||||
goto error;
|
||||
diff -Nur freeradius-server-3.2.3_bak/src/main/tls_listen.c freeradius-server-3.2.3/src/main/tls_listen.c
|
||||
--- freeradius-server-3.2.3_bak/src/main/tls_listen.c 2024-07-16 16:46:31.265616699 +0800
|
||||
+++ freeradius-server-3.2.3/src/main/tls_listen.c 2024-07-16 16:49:00.185840125 +0800
|
||||
@@ -674,6 +674,8 @@
|
||||
packet->radiusv11 = sock->radiusv11;
|
||||
#endif
|
||||
|
||||
+ packet->tls = true;
|
||||
+
|
||||
if (!rad_packet_ok(packet, 0, NULL)) {
|
||||
if (DEBUG_ENABLED) ERROR("Receive - %s", fr_strerror());
|
||||
DEBUG("(TLS) Closing TLS socket from client");
|
||||
@@ -1286,6 +1288,7 @@
|
||||
}
|
||||
|
||||
#endif
|
||||
+ packet->tls = true;
|
||||
|
||||
/*
|
||||
* FIXME: Client MIB updates?
|
||||
@@ -1322,7 +1325,6 @@
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
-
|
||||
default:
|
||||
#ifdef WITH_COA_TUNNEL
|
||||
bad_packet:
|
||||
@@ -1373,6 +1375,7 @@
|
||||
* if there's no packet, encode it here.
|
||||
*/
|
||||
if (!request->proxy->data) {
|
||||
+ request->reply->tls = true;
|
||||
request->proxy_listener->proxy_encode(request->proxy_listener,
|
||||
request);
|
||||
}
|
||||
@@ -1508,6 +1511,8 @@
|
||||
if ((listener->status != RAD_LISTEN_STATUS_INIT &&
|
||||
(listener->status != RAD_LISTEN_STATUS_KNOWN))) return 0;
|
||||
|
||||
+ request->reply->tls = true;
|
||||
+
|
||||
/*
|
||||
* Pack the VPs
|
||||
*/
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
Name: freeradius
|
||||
Version: 3.2.3
|
||||
Release: 1
|
||||
Release: 2
|
||||
Summary: Remote Authentication Dial-In User Service
|
||||
|
||||
License: GPLv2+ and LGPLv2+
|
||||
@ -14,6 +14,7 @@ Source1: radiusd.service
|
||||
Source2: freeradius-logrotate
|
||||
Source3: freeradius-pam-conf
|
||||
Source4: freeradius-tmpfiles.conf
|
||||
Patch0: CVE-2024-3596.patch
|
||||
|
||||
BuildRequires: autoconf gdbm-devel openssl openssl-devel pam-devel zlib-devel net-snmp-devel
|
||||
BuildRequires: net-snmp-utils readline-devel libpcap-devel systemd-units libtalloc-devel
|
||||
@ -496,6 +497,9 @@ exit 0
|
||||
%attr(640,root,radiusd) %config(noreplace) /etc/raddb/mods-available/ldap
|
||||
|
||||
%changelog
|
||||
* Tue Jul 16 2024 wangkai <13474090681@163.com> - 3.2.3-2
|
||||
- Fix CVE-2024-3596
|
||||
|
||||
* Thu Sep 28 2023 xu_ping <707078654@qq.com> - 3.2.3-1
|
||||
- Update to 3.2.3
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user