]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
use and enforce limit_proxy_state for Access-Request packets
authorAlan T. DeKok <aland@freeradius.org>
Thu, 22 Feb 2024 11:01:22 +0000 (06:01 -0500)
committerMatthew Newton <matthew-git@newtoncomputing.co.uk>
Mon, 8 Jul 2024 15:22:10 +0000 (16:22 +0100)
src/include/libradius.h
src/lib/radius.c
src/main/listen.c

index 36fe87fc9e504eff66fc25e566545e9001cacf55..018a018f9e5182495024c6ad8dc3121bd6aca335 100644 (file)
@@ -528,6 +528,12 @@ DICT_VENDOR        *dict_vendorbyvalue(int vendor);
 /* 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);
index 8f1e558e44ddd57cded9467f9fe506c9eb75b38b..6cd2b84bb40ccde03cd58724c9613d3505cccf60 100644 (file)
@@ -2527,6 +2527,8 @@ bool rad_packet_ok(RADIUS_PACKET *packet, int flags, decode_fail_t *reason)
        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;
@@ -2578,13 +2580,14 @@ bool rad_packet_ok(RADIUS_PACKET *packet, int flags, decode_fail_t *reason)
        /*
         *      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
@@ -2748,6 +2751,10 @@ bool rad_packet_ok(RADIUS_PACKET *packet, int flags, decode_fail_t *reason)
                        non_eap = true;
                        break;
 
+               case PW_PROXY_STATE:
+                       seen_proxy_state = true;
+                       break;
+
                case PW_MESSAGE_AUTHENTICATOR:
 #ifdef WITH_RADIUSV11
                        /*
@@ -2839,6 +2846,18 @@ bool rad_packet_ok(RADIUS_PACKET *packet, int flags, decode_fail_t *reason)
        }
 
 #ifndef WITH_RADIUSV11_ONLY
+       /*
+        *      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;
+       }
+
        if (eap && non_eap) {
                FR_DEBUG_STRERROR_PRINTF("Bad packet from host %s:  Packet contains EAP-Message and non-EAP authentication attribute",
                           inet_ntop(packet->src_ipaddr.af,
index 407d33ce3c6e6f38043e0f0bf5c180f00cb48f83..f1627268667469757f16d1797cccada5a90cdfce 100644 (file)
@@ -2027,7 +2027,7 @@ static int auth_socket_recv(rad_listen_t *listener)
         *      Now that we've sanity checked everything, receive the
         *      packet.
         */
-       packet = rad_recv(ctx, listener->fd, client->require_ma);
+       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());