From: Alan T. DeKok Date: Fri, 30 Jan 2026 13:09:26 +0000 (-0500) Subject: add more decode errors, and add reason to decode_ctx X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f6052c5417692db29730ba61f24b1f856a585e2c;p=thirdparty%2Ffreeradius-server.git add more decode errors, and add reason to decode_ctx --- diff --git a/src/modules/rlm_radius/bio.c b/src/modules/rlm_radius/bio.c index 839d02cc784..122c86715bc 100644 --- a/src/modules/rlm_radius/bio.c +++ b/src/modules/rlm_radius/bio.c @@ -1215,7 +1215,7 @@ static fr_radius_decode_fail_t decode(TALLOC_CTX *ctx, fr_pair_list_t *reply, ui if (fr_radius_decode(ctx, reply, data, data_len, &decode_ctx) < 0) { talloc_free(decode_ctx.tmp_ctx); RPEDEBUG("Failed reading packet"); - return FR_RADIUS_FAIL_UNKNOWN; + return decode_ctx.reason; } talloc_free(decode_ctx.tmp_ctx); diff --git a/src/protocols/radius/base.c b/src/protocols/radius/base.c index 629626d6754..01b878a788a 100644 --- a/src/protocols/radius/base.c +++ b/src/protocols/radius/base.c @@ -521,6 +521,7 @@ char const *fr_radius_decode_fail_reason[FR_RADIUS_FAIL_MAX + 1] = { [FR_RADIUS_FAIL_HEADER_OVERFLOW] = "attribute header overflows the packet", [FR_RADIUS_FAIL_ATTRIBUTE_TOO_SHORT] = "attribute 'length' field contains invalid value", [FR_RADIUS_FAIL_ATTRIBUTE_OVERFLOW] = "attribute 'length' field overflows the packet", + [FR_RADIUS_FAIL_ATTRIBUTE_DECODE] = "unable to decode attributes", [FR_RADIUS_FAIL_MA_INVALID_LENGTH] = "Message-Authenticate has invalid length", [FR_RADIUS_FAIL_MA_MISSING] = "Message-Authenticator is required for this packet, but it is missing", @@ -528,7 +529,7 @@ char const *fr_radius_decode_fail_reason[FR_RADIUS_FAIL_MAX + 1] = { [FR_RADIUS_FAIL_PROXY_STATE_MISSING] = "Proxy-State is required for this request, but it is missing", [FR_RADIUS_FAIL_VERIFY] = "packet fails verification (shared secret is incorrect)", - [FR_RADIUS_FAIL_UNKNOWN] = "???", + [FR_RADIUS_FAIL_NO_MATCHING_REQUEST] = "did not find request which matched response", [FR_RADIUS_FAIL_MAX] = "???", }; @@ -1107,6 +1108,8 @@ ssize_t fr_radius_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *attr, *end; static const uint8_t zeros[RADIUS_AUTH_VECTOR_LENGTH] = {}; + decode_ctx->reason = FR_RADIUS_FAIL_NONE; + if (!decode_ctx->request_authenticator) { switch (packet[0]) { case FR_RADIUS_CODE_ACCESS_REQUEST: @@ -1122,6 +1125,7 @@ ssize_t fr_radius_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, default: fr_strerror_const("No authentication vector passed for packet decode"); + decode_ctx->reason = FR_RADIUS_FAIL_NO_MATCHING_REQUEST; return -1; } } @@ -1130,16 +1134,17 @@ ssize_t fr_radius_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, unsigned int code = packet[0]; if (code >= FR_RADIUS_CODE_MAX) { - return -FR_RADIUS_FAIL_UNKNOWN_PACKET_CODE; + decode_ctx->reason = FR_RADIUS_FAIL_UNKNOWN_PACKET_CODE; + return -1; } if (decode_ctx->request_code >= FR_RADIUS_CODE_MAX) { - return -FR_RADIUS_FAIL_UNKNOWN_PACKET_CODE; + decode_ctx->reason = FR_RADIUS_FAIL_UNKNOWN_PACKET_CODE; + return -1; } if (!allowed_replies[code]) { - fr_strerror_printf("%s packet received unknown reply code %s", - fr_radius_packet_name[decode_ctx->request_code], fr_radius_packet_name[code]); - return -FR_RADIUS_FAIL_UNKNOWN_PACKET_CODE; + decode_ctx->reason = FR_RADIUS_FAIL_UNEXPECTED_RESPONSE_CODE; + return -1; } /* @@ -1152,9 +1157,8 @@ ssize_t fr_radius_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, if ((allowed_replies[code] != decode_ctx->request_code) && (code != FR_RADIUS_CODE_PROTOCOL_ERROR) && (decode_ctx->request_code != FR_RADIUS_CODE_STATUS_SERVER)) { - fr_strerror_printf("%s packet received invalid reply code %s", - fr_radius_packet_name[decode_ctx->request_code], fr_radius_packet_name[code]); - return -FR_RADIUS_FAIL_UNKNOWN_PACKET_CODE; + decode_ctx->reason = FR_RADIUS_FAIL_UNEXPECTED_RESPONSE_CODE; + return -1; } } @@ -1168,6 +1172,7 @@ ssize_t fr_radius_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, if (fr_radius_verify(packet, decode_ctx->request_authenticator, (uint8_t const *) decode_ctx->common->secret, decode_ctx->common->secret_length, decode_ctx->require_message_authenticator, decode_ctx->limit_proxy_state) < 0) { + decode_ctx->reason = FR_RADIUS_FAIL_VERIFY; return -1; } } @@ -1181,7 +1186,10 @@ ssize_t fr_radius_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, */ while (attr < end) { slen = fr_radius_decode_pair(ctx, out, attr, (end - attr), decode_ctx); - if (slen < 0) return slen; + if (slen < 0) { + decode_ctx->reason = FR_RADIUS_FAIL_ATTRIBUTE_DECODE; + return slen; + } /* * If slen is larger than the room in the packet, diff --git a/src/protocols/radius/radius.h b/src/protocols/radius/radius.h index 3cb9fcfd7f4..d0fc62e72ee 100644 --- a/src/protocols/radius/radius.h +++ b/src/protocols/radius/radius.h @@ -86,6 +86,37 @@ typedef enum { ///< to drive logic in modules. } fr_radius_limit_proxy_state_t; +/** Failure reasons */ +typedef enum { + FR_RADIUS_FAIL_NONE = 0, + FR_RADIUS_FAIL_MIN_LENGTH_PACKET, + FR_RADIUS_FAIL_MAX_LENGTH_PACKET, + FR_RADIUS_FAIL_MIN_LENGTH_FIELD, + FR_RADIUS_FAIL_MIN_LENGTH_MISMATCH, + FR_RADIUS_FAIL_UNKNOWN_PACKET_CODE, + FR_RADIUS_FAIL_UNEXPECTED_REQUEST_CODE, + FR_RADIUS_FAIL_UNEXPECTED_RESPONSE_CODE, + FR_RADIUS_FAIL_TOO_MANY_ATTRIBUTES, + + FR_RADIUS_FAIL_INVALID_ATTRIBUTE, + + FR_RADIUS_FAIL_HEADER_OVERFLOW, + FR_RADIUS_FAIL_ATTRIBUTE_TOO_SHORT, + FR_RADIUS_FAIL_ATTRIBUTE_OVERFLOW, + FR_RADIUS_FAIL_ATTRIBUTE_DECODE, + + FR_RADIUS_FAIL_MA_INVALID_LENGTH, + FR_RADIUS_FAIL_MA_MISSING, + FR_RADIUS_FAIL_MA_INVALID, + FR_RADIUS_FAIL_PROXY_STATE_MISSING, + + FR_RADIUS_FAIL_VERIFY, + FR_RADIUS_FAIL_NO_MATCHING_REQUEST, + FR_RADIUS_FAIL_MAX +} fr_radius_decode_fail_t; + +extern char const *fr_radius_decode_fail_reason[FR_RADIUS_FAIL_MAX + 1]; + typedef struct { fr_pair_t *parent; fr_dcursor_t cursor; @@ -132,6 +163,8 @@ typedef struct { TALLOC_CTX *tmp_ctx; //!< for temporary things cleaned up during decoding uint8_t const *end; //!< end of the packet + fr_radius_decode_fail_t reason; //!< reason for decode failure + uint8_t request_code; //!< original code for the request. bool tunnel_password_zeros; //!< check for trailing zeros on decode @@ -161,36 +194,6 @@ typedef struct { fr_radius_attr_flags_encrypt_t encrypt; //!< Attribute is encrypted } fr_radius_attr_flags_t; -/** Failure reasons */ -typedef enum { - FR_RADIUS_FAIL_NONE = 0, - FR_RADIUS_FAIL_MIN_LENGTH_PACKET, - FR_RADIUS_FAIL_MAX_LENGTH_PACKET, - FR_RADIUS_FAIL_MIN_LENGTH_FIELD, - FR_RADIUS_FAIL_MIN_LENGTH_MISMATCH, - FR_RADIUS_FAIL_UNKNOWN_PACKET_CODE, - FR_RADIUS_FAIL_UNEXPECTED_REQUEST_CODE, - FR_RADIUS_FAIL_UNEXPECTED_RESPONSE_CODE, - FR_RADIUS_FAIL_TOO_MANY_ATTRIBUTES, - - FR_RADIUS_FAIL_INVALID_ATTRIBUTE, - - FR_RADIUS_FAIL_HEADER_OVERFLOW, - FR_RADIUS_FAIL_ATTRIBUTE_TOO_SHORT, - FR_RADIUS_FAIL_ATTRIBUTE_OVERFLOW, - - FR_RADIUS_FAIL_MA_INVALID_LENGTH, - FR_RADIUS_FAIL_MA_MISSING, - FR_RADIUS_FAIL_MA_INVALID, - FR_RADIUS_FAIL_PROXY_STATE_MISSING, - - FR_RADIUS_FAIL_VERIFY, - FR_RADIUS_FAIL_UNKNOWN, - FR_RADIUS_FAIL_MAX -} fr_radius_decode_fail_t; - -extern char const *fr_radius_decode_fail_reason[FR_RADIUS_FAIL_MAX + 1]; - DIAG_OFF(unused-function) /** Return RADIUS-specific flags for a given attribute */