From: Alan T. DeKok Date: Thu, 22 Feb 2024 11:01:22 +0000 (-0500) Subject: use and enforce limit_proxy_state for Access-Request packets X-Git-Tag: release_3_2_5~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=80838f43725353daeb58dffe3ff24d0ea9350867;p=thirdparty%2Ffreeradius-server.git use and enforce limit_proxy_state for Access-Request packets --- diff --git a/src/include/libradius.h b/src/include/libradius.h index 36fe87fc9e5..018a018f9e5 100644 --- a/src/include/libradius.h +++ b/src/include/libradius.h @@ -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); diff --git a/src/lib/radius.c b/src/lib/radius.c index 8f1e558e44d..6cd2b84bb40 100644 --- a/src/lib/radius.c +++ b/src/lib/radius.c @@ -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, diff --git a/src/main/listen.c b/src/main/listen.c index 407d33ce3c6..f1627268667 100644 --- a/src/main/listen.c +++ b/src/main/listen.c @@ -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());