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_0_27~13 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=099c41632dbd6137eb6874a8ecf9eb7dc31232fa;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 c2e8969f3c..89ac672462 100644 --- a/src/include/libradius.h +++ b/src/include/libradius.h @@ -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); diff --git a/src/lib/radius.c b/src/lib/radius.c index d4b606c0f6..094c511bd3 100644 --- a/src/lib/radius.c +++ b/src/lib/radius.c @@ -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, diff --git a/src/main/listen.c b/src/main/listen.c index e9d62e5e5c..48be47564c 100644 --- a/src/main/listen.c +++ b/src/main/listen.c @@ -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());