]> 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 19:38:15 +0000 (20:38 +0100)
src/include/libradius.h
src/lib/radius.c
src/main/listen.c

index c2e8969f3c9893798fe7197017e352126b664b32..89ac67246251f004d166f6d24714c61e5f884836 100644 (file)
@@ -515,6 +515,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 d4b606c0f691d5c5893acf05e5455bcd2847867d..094c511bd3f010501e9b56624b0e27459cba26d5 100644 (file)
@@ -2450,6 +2450,8 @@ bool rad_packet_ok(RADIUS_PACKET *packet, int flags, decode_fail_t *reason)
        radius_packet_t         *hdr;
        char                    host_ipaddr[128];
        bool                    require_ma = false;
+       bool                    limit_proxy_state = false;
+       bool                    seen_proxy_state = false;
        bool                    seen_ma = false;
        uint32_t                num_attributes;
        decode_fail_t           failure = DECODE_FAIL_NONE;
@@ -2500,13 +2502,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
@@ -2669,6 +2672,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:
                        if (attr[1] != 2 + AUTH_VECTOR_LEN) {
                                FR_DEBUG_STRERROR_PRINTF("Malformed RADIUS packet from host %s: Message-Authenticator has invalid length %d",
@@ -2744,6 +2751,18 @@ bool rad_packet_ok(RADIUS_PACKET *packet, int flags, decode_fail_t *reason)
                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;
+       }
+
        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 e9d62e5e5ca8180f43c9ba8eb285c1e7f44fd2bd..48be47564c1e4623218380f39b783e1314b3ea3a 100644 (file)
@@ -1668,7 +1668,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());