]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add more decode errors, and add reason to decode_ctx
authorAlan T. DeKok <aland@freeradius.org>
Fri, 30 Jan 2026 13:09:26 +0000 (08:09 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Fri, 30 Jan 2026 13:09:26 +0000 (08:09 -0500)
src/modules/rlm_radius/bio.c
src/protocols/radius/base.c
src/protocols/radius/radius.h

index 839d02cc7842f3d01f92dcdb925b9ce973a2f107..122c86715bc4f1df716f1853abed9da294ac73f8 100644 (file)
@@ -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);
 
index 629626d6754a3150cefaedbde3311b1e3f4456f9..01b878a788a4095d296e03adf979f7ea33f4b322 100644 (file)
@@ -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,
index 3cb9fcfd7f4f01f53bcb414e977d2286e2b424d7..d0fc62e72eeddfacbbf443d0d1914b1db14cb506 100644 (file)
@@ -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
  */