return 0;
}
+char const *fr_radius_decode_fail_reason[DECODE_FAIL_MAX + 1] = {
+ [DECODE_FAIL_NONE] = "none",
+ [DECODE_FAIL_MIN_LENGTH_PACKET] = "packet is smaller than the minimum packet length",
+ [DECODE_FAIL_MAX_LENGTH_PACKET] = "packet is larger than the maximum packet length",
+ [DECODE_FAIL_MIN_LENGTH_FIELD] = "header 'length' field has a value smaller than the minimum packet length",
+ [DECODE_FAIL_MIN_LENGTH_MISMATCH] = "header 'length' field has a value larger than the received data",
+ [DECODE_FAIL_UNKNOWN_PACKET_CODE] = "unknown packet code",
+ [DECODE_FAIL_UNEXPECTED_REQUEST_CODE] = "unexpected request code",
+ [DECODE_FAIL_UNEXPECTED_RESPONSE_CODE] = "unexpected response code",
+ [DECODE_FAIL_TOO_MANY_ATTRIBUTES] = "packet contains too many attributes",
+
+ [DECODE_FAIL_INVALID_ATTRIBUTE] = "attribute number 0 is invalid",
+
+ [DECODE_FAIL_HEADER_OVERFLOW] = "attribute header overflows the packet",
+ [DECODE_FAIL_ATTRIBUTE_TOO_SHORT] = "attribute 'length' field contains invalid value",
+ [DECODE_FAIL_ATTRIBUTE_OVERFLOW] = "attribute 'length' field overflows the packet",
+
+ [DECODE_FAIL_MA_INVALID_LENGTH] = "Message-Authenticate has invalid length",
+ [DECODE_FAIL_MA_MISSING] = "Message-Authenticator is required for this packet, but it is missing",
+ [DECODE_FAIL_MA_INVALID] = "Message-Authenticator fails verification (shared secret is incorrect)",
+ [DECODE_FAIL_PROXY_STATE_MISSING] = "Proxy-State is required for this request, but it is missing",
+
+ [DECODE_FAIL_VERIFY] = "packet fails verification (shared secret is incorrect)",
+ [DECODE_FAIL_UNKNOWN] = "???",
+ [DECODE_FAIL_MAX] = "???",
+};
/** See if the data pointed to by PTR is a valid RADIUS packet.
*
* "The minimum length is 20 ..."
*/
if (packet_len < RADIUS_HEADER_LENGTH) {
- FR_DEBUG_STRERROR_PRINTF("Packet is too short (received %zu < minimum 20)",
- packet_len);
failure = DECODE_FAIL_MIN_LENGTH_PACKET;
goto finish;
}
*/
if ((packet[0] == 0) ||
(packet[0] >= FR_RADIUS_CODE_MAX)) {
- FR_DEBUG_STRERROR_PRINTF("Unknown packet code %d", packet[0]);
failure = DECODE_FAIL_UNKNOWN_PACKET_CODE;
goto finish;
}
break;
/*
- * Message-Authenticator is not required for all other packets.
+ * Message-Authenticator is not required for all other packets, but is required if the
+ * caller asks for it.
*/
default:
- require_message_authenticator = false;
break;
}
* "The minimum length is 20 ..."
*/
if (totallen < RADIUS_HEADER_LENGTH) {
- FR_DEBUG_STRERROR_PRINTF("Length in header is too small (length %zu < minimum 20)",
- totallen);
failure = DECODE_FAIL_MIN_LENGTH_FIELD;
goto finish;
}
* i.e. No response to the NAS.
*/
if (totallen > packet_len) {
- FR_DEBUG_STRERROR_PRINTF("Packet is truncated (received %zu < packet header length of %zu)",
- packet_len, totallen);
failure = DECODE_FAIL_MIN_LENGTH_MISMATCH;
goto finish;
}
* attribute header.
*/
if ((end - attr) < 2) {
- FR_DEBUG_STRERROR_PRINTF("Attribute header overflows the packet");
failure = DECODE_FAIL_HEADER_OVERFLOW;
goto finish;
}
* Attribute number zero is NOT defined.
*/
if (attr[0] == 0) {
- FR_DEBUG_STRERROR_PRINTF("Invalid attribute 0 at offset %zd", attr - packet);
failure = DECODE_FAIL_INVALID_ATTRIBUTE;
goto finish;
}
* fields. Anything shorter is an invalid attribute.
*/
if (attr[1] < 2) {
- FR_DEBUG_STRERROR_PRINTF("Attribute %u is too short at offset %zd",
- attr[0], attr - packet);
failure = DECODE_FAIL_ATTRIBUTE_TOO_SHORT;
goto finish;
}
* attribute, it's a bad packet.
*/
if ((attr + attr[1]) > end) {
- FR_DEBUG_STRERROR_PRINTF("Attribute %u data overflows the packet starting at offset %zd",
- attr[0], attr - packet);
failure = DECODE_FAIL_ATTRIBUTE_OVERFLOW;
goto finish;
}
case FR_MESSAGE_AUTHENTICATOR:
if (attr[1] != 2 + RADIUS_AUTH_VECTOR_LENGTH) {
- FR_DEBUG_STRERROR_PRINTF("Message-Authenticator has invalid length (%d != 18) at offset %zd",
- attr[1] - 2, attr - packet);
failure = DECODE_FAIL_MA_INVALID_LENGTH;
goto finish;
}
num_attributes++; /* seen one more attribute */
}
- /*
- * If the attributes add up to a packet, it's allowed.
- *
- * If not, we complain, and throw the packet away.
- */
- if (attr != end) {
- FR_DEBUG_STRERROR_PRINTF("Attributes do NOT exactly fill the packet");
- failure = DECODE_FAIL_ATTRIBUTE_UNDERFLOW;
- goto finish;
- }
-
/*
* If we're configured to look for a maximum number of
* attributes, and we've seen more than that maximum,
* then throw the packet away, as a possible DoS.
*/
- if ((max_attributes > 0) &&
- (num_attributes > max_attributes)) {
- FR_DEBUG_STRERROR_PRINTF("Possible DoS attack - too many attributes in request (received %u, max %u are allowed).",
- num_attributes, max_attributes);
+ if (num_attributes > max_attributes) {
failure = DECODE_FAIL_TOO_MANY_ATTRIBUTES;
goto finish;
}
* Message-Authenticator attributes.
*/
if (require_message_authenticator && !seen_ma) {
- FR_DEBUG_STRERROR_PRINTF("We require Message-Authenticator attribute, but it is not in the packet");
failure = DECODE_FAIL_MA_MISSING;
goto finish;
}
finish:
- if (reason) {
- *reason = failure;
- }
+ if (reason) *reason = failure;
+
return (failure == DECODE_FAIL_NONE);
}
return 0;
}
-static const char *reason_name[DECODE_FAIL_MAX] = {
- [ DECODE_FAIL_NONE ] = "all OK",
- [ DECODE_FAIL_MIN_LENGTH_PACKET ] = "packet is too small",
- [ DECODE_FAIL_MAX_LENGTH_PACKET ] = "packet is too large",
- [ DECODE_FAIL_MIN_LENGTH_FIELD ] = "length field is too small",
- [ DECODE_FAIL_MIN_LENGTH_MISMATCH ] = "length mismatch",
- [ DECODE_FAIL_HEADER_OVERFLOW ] = "header overflow",
- [ DECODE_FAIL_UNKNOWN_PACKET_CODE ] = "unknown packet code",
- [ DECODE_FAIL_INVALID_ATTRIBUTE ] = "invalid attribute",
- [ DECODE_FAIL_ATTRIBUTE_TOO_SHORT ] = "attribute too short",
- [ DECODE_FAIL_ATTRIBUTE_OVERFLOW ] = "attribute overflows the packet",
- [ DECODE_FAIL_MA_INVALID_LENGTH ] = "invalid length for Message-Authenticator",
- [ DECODE_FAIL_ATTRIBUTE_UNDERFLOW ] = "attribute underflows the packet",
- [ DECODE_FAIL_TOO_MANY_ATTRIBUTES ] = "too many attributes",
- [ DECODE_FAIL_MA_MISSING ] = "Message-Authenticator is required, but missing",
- [ DECODE_FAIL_MA_INVALID ] = "Message-Authenticator is invalid",
- [ DECODE_FAIL_VERIFY ] = "Authenticator is invalid",
- [ DECODE_FAIL_UNKNOWN ] = "unknown",
-};
-
static ssize_t fr_radius_decode_proto(TALLOC_CTX *ctx, fr_pair_list_t *out,
uint8_t const *data, size_t data_len, void *proto_ctx)
{
size_t packet_len = data_len;
if (!fr_radius_ok(data, &packet_len, 200, false, &reason)) {
- fr_strerror_printf("Packet failed verification - %s", reason_name[reason]);
+ fr_strerror_printf("Packet failed verification - %s", fr_radius_decode_fail_reason[reason]);
return -1;
}
DECODE_FAIL_MAX_LENGTH_PACKET,
DECODE_FAIL_MIN_LENGTH_FIELD,
DECODE_FAIL_MIN_LENGTH_MISMATCH,
- DECODE_FAIL_HEADER_OVERFLOW,
DECODE_FAIL_UNKNOWN_PACKET_CODE,
+ DECODE_FAIL_UNEXPECTED_REQUEST_CODE,
+ DECODE_FAIL_UNEXPECTED_RESPONSE_CODE,
+ DECODE_FAIL_TOO_MANY_ATTRIBUTES,
+
DECODE_FAIL_INVALID_ATTRIBUTE,
+
+ DECODE_FAIL_HEADER_OVERFLOW,
DECODE_FAIL_ATTRIBUTE_TOO_SHORT,
DECODE_FAIL_ATTRIBUTE_OVERFLOW,
+
DECODE_FAIL_MA_INVALID_LENGTH,
- DECODE_FAIL_ATTRIBUTE_UNDERFLOW,
- DECODE_FAIL_TOO_MANY_ATTRIBUTES,
DECODE_FAIL_MA_MISSING,
DECODE_FAIL_MA_INVALID,
+ DECODE_FAIL_PROXY_STATE_MISSING,
+
DECODE_FAIL_VERIFY,
DECODE_FAIL_UNKNOWN,
DECODE_FAIL_MAX
} fr_radius_decode_fail_t;
+extern char const *fr_radius_decode_fail_reason[DECODE_FAIL_MAX + 1];
DIAG_OFF(unused-function)
/** Return RADIUS-specific flags for a given attribute