]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add M-A processing for Status-Server and replies from home server
authorAlan T. DeKok <aland@freeradius.org>
Sat, 11 May 2024 19:41:03 +0000 (15:41 -0400)
committerMatthew Newton <matthew-git@newtoncomputing.co.uk>
Mon, 8 Jul 2024 19:40:57 +0000 (20:40 +0100)
src/include/libradius.h
src/include/radius.h
src/lib/radius.c
src/main/listen.c

index 89ac67246251f004d166f6d24714c61e5f884836..b5d1db81bdf76dd0a85225fcf9287944f2513a83 100644 (file)
@@ -519,7 +519,8 @@ bool                rad_packet_ok(RADIUS_PACKET *packet, int flags, decode_fail_t *reason);
 /*
  *     1 == require_ma
  *     2 == msg_peek
- *     3 == limit_proxy_state
+ *     4 == limit_proxy_state
+ *     8 == require_ma for Access-* replies and Protocol-Error
  */
 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);
@@ -710,7 +711,7 @@ extern bool fr_dns_lookups; /* do IP -> hostname lookups? */
 extern bool    fr_hostname_lookups; /* do hostname -> IP lookups? */
 extern int     fr_debug_lvl;   /* 0 = no debugging information */
 extern uint32_t        fr_max_attributes; /* per incoming packet */
-#define        FR_MAX_PACKET_CODE (52)
+#define        FR_MAX_PACKET_CODE (53)
 extern char const *fr_packet_codes[FR_MAX_PACKET_CODE];
 #define is_radius_code(_x) ((_x > 0) && (_x < FR_MAX_PACKET_CODE))
 extern FILE    *fr_log_fp;
index 473528d65dbe552dee8f42315d30dc2c13e6ab14..147d674eed9373897664a3c37aa23828648655e0 100644 (file)
@@ -61,6 +61,7 @@ typedef enum {
        PW_CODE_COA_REQUEST             = 43,   //!< RFC3575/RFC5176 - CoA-Request
        PW_CODE_COA_ACK                 = 44,   //!< RFC3575/RFC5176 - CoA-Ack (positive)
        PW_CODE_COA_NAK                 = 45,   //!< RFC3575/RFC5176 - CoA-Nak (not willing to perform)
+       PW_CODE_PROTOCOL_ERROR          = 52,   //!< RFC7930 - Protocol layer issue
        PW_CODE_MAX                     = 255,  //!< Maximum possible code
 } PW_CODE;
 
index 094c511bd3f010501e9b56624b0e27459cba26d5..10e40bac5ee92bc4e42c6e42bc396fff00350ed3 100644 (file)
@@ -143,8 +143,9 @@ char const *fr_packet_codes[FR_MAX_PACKET_CODE] = {
   "47",
   "48",
   "49",
-  "IP-Address-Allocate",
-  "IP-Address-Release",                        //!< 50
+  "IP-Address-Allocate",               //!< 50
+  "IP-Address-Release",
+  "Protocol-Error",
 };
 
 
@@ -1794,6 +1795,14 @@ int rad_vp2attr(RADIUS_PACKET const *packet, RADIUS_PACKET const *original,
        return rad_vp2vsa(packet, original, secret, pvp, start, room);
 }
 
+static const bool code2ma[FR_MAX_PACKET_CODE] = {
+       [ PW_CODE_ACCESS_REQUEST ] = true,
+       [ PW_CODE_ACCESS_ACCEPT ] = true,
+       [ PW_CODE_ACCESS_REJECT ] = true,
+       [ PW_CODE_ACCESS_CHALLENGE ] = true,
+       [ PW_CODE_STATUS_SERVER ] = true,
+       [ PW_CODE_PROTOCOL_ERROR ] = true,
+};
 
 /** Encode a packet
  *
@@ -1872,13 +1881,13 @@ int rad_encode(RADIUS_PACKET *packet, RADIUS_PACKET const *original,
 
        /*
         *      Always add Message-Authenticator for replies to
-        *      Access-Request packets.
+        *      Access-Request packets, and for all Access-Accept,
+        *      Access-Reject, Access-Challenge.
         *
         *      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))) {
+       if (!packet->tls &&
+           ((code2ma[packet->code]) || (original && code2ma[original->code]))) {
                seen_ma = true;
 
                packet->offset = RADIUS_HDR_LEN;
@@ -2500,16 +2509,23 @@ 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 the caller requires Message-Authenticator, then set
+        *      the flag.
         *
-        *      It's also required if the caller asks for it.
+        *      We also require Message-Authenticator if the packet
+        *      code is Status-Server.
         *
+        *      If we're receiving packets from a proxy socket, then
+        *      require Message-Authenticator for Access-* replies,
+        *      and for Protocol-Error.
+        */
+       require_ma = ((flags & 0x01) != 0) || (hdr->code == PW_CODE_STATUS_SERVER) || (((flags & 0x08) != 0) && code2ma[hdr->code]);
+
+       /*
         *      We only limit Proxy-State if we're not requiring
         *      Message-Authenticator.
         */
-       require_ma = ((flags & 0x01) != 0) || (hdr->code == PW_CODE_STATUS_SERVER);
-       limit_proxy_state = ((flags & 0x04) != 0) & !require_ma;
+       limit_proxy_state = ((flags & 0x04) != 0) && !require_ma;
 
        /*
         *      Repeat the length checks.  This time, instead of
index 48be47564c1e4623218380f39b783e1314b3ea3a..8f74f7d629810aa6c231f05fdcc23ff2ad7257f9 100644 (file)
@@ -2090,7 +2090,7 @@ static int proxy_socket_recv(rad_listen_t *listener)
 #endif
        char            buffer[128];
 
-       packet = rad_recv(NULL, listener->fd, 0);
+       packet = rad_recv(NULL, listener->fd, 8); /* SOME packets don't require a Message-Authenticator attribute */
        if (!packet) {
                if (DEBUG_ENABLED) ERROR("Receive - %s", fr_strerror());
                return 0;