From: Arran Cudbard-Bell Date: Fri, 6 Mar 2020 21:48:24 +0000 (-0600) Subject: pair: Establish error codes for decoders X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ea0d2e577a9e4b806d263132c7c9db59ac7715d0;p=thirdparty%2Ffreeradius-server.git pair: Establish error codes for decoders --- diff --git a/src/lib/eap_aka_sim/encode.c b/src/lib/eap_aka_sim/encode.c index e38e3b58472..df07eaa10d5 100644 --- a/src/lib/eap_aka_sim/encode.c +++ b/src/lib/eap_aka_sim/encode.c @@ -192,7 +192,7 @@ static ssize_t encode_encrypted_value(uint8_t *out, size_t outlen, */ if (unlikely(inlen % 4)) { fr_strerror_printf("%s: Input data length is not a multiple of 4", __FUNCTION__); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } total_len = (inlen + (block_size - 1)) & ~(block_size - 1); /* Round input length to block size (16) */ @@ -219,7 +219,7 @@ static ssize_t encode_encrypted_value(uint8_t *out, size_t outlen, evp_ctx = EVP_CIPHER_CTX_new(); if (!evp_ctx) { tls_strerror_printf("Failed allocating EVP context"); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } if (unlikely(EVP_EncryptInit_ex(evp_ctx, evp_cipher, NULL, @@ -228,7 +228,7 @@ static ssize_t encode_encrypted_value(uint8_t *out, size_t outlen, error: talloc_free(encr); EVP_CIPHER_CTX_free(evp_ctx); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } encr = talloc_array(NULL, uint8_t, total_len); @@ -308,19 +308,19 @@ static ssize_t encode_value(uint8_t *out, size_t outlen, if (unlikely(tlv_stack[depth + 1] != NULL)) { fr_strerror_printf("%s: Encoding value but not at top of stack", __FUNCTION__); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } if (unlikely(vp->da != da)) { fr_strerror_printf("%s: Top of stack does not match vp->da", __FUNCTION__); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } switch (da->type) { case FR_TYPE_STRUCTURAL: fr_strerror_printf("%s: Called with structural type %s", __FUNCTION__, fr_table_str_by_value(fr_value_box_type_table, tlv_stack[depth]->type, "?Unknown?")); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; default: break; @@ -347,7 +347,7 @@ static ssize_t encode_value(uint8_t *out, size_t outlen, fr_strerror_printf("%s: Attribute \"%s\" needs a value of exactly %zu bytes, " "but value was %zu bytes", __FUNCTION__, da->name, (size_t)da->flags.length, vp->vp_length); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } memcpy(packet_ctx->iv, vp->vp_octets, sizeof(packet_ctx->iv)); packet_ctx->iv_included = true; @@ -376,7 +376,7 @@ static ssize_t encode_value(uint8_t *out, size_t outlen, if ((vp->vp_length < 4) || (vp->vp_length > 16)) { fr_strerror_printf("%s: AKA-RES Length must be between 4-16 bytes, got %zu bytes", __FUNCTION__, vp->vp_length); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } CHECK_FREESPACE(outlen, vp->vp_length + 2); @@ -455,7 +455,7 @@ static ssize_t encode_value(uint8_t *out, size_t outlen, fr_strerror_printf("%s: Attribute \"%s\" needs a value of exactly %zu bytes, " "but value was %zu bytes", __FUNCTION__, vp->da->name, (size_t)vp->da->flags.length, vp->vp_length); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } memcpy(p, &actual_len, sizeof(actual_len)); /* Big endian real string length */ @@ -484,7 +484,7 @@ static ssize_t encode_value(uint8_t *out, size_t outlen, fr_strerror_printf("%s: Attribute \"%s\" needs a value of <= %zu bytes, " "but value was %zu bytes", __FUNCTION__, vp->da->name, (size_t)vp->da->flags.length, vp->vp_length); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } /* @@ -575,7 +575,7 @@ static ssize_t encode_value(uint8_t *out, size_t outlen, default: fr_strerror_printf("%s: Cannot encode attribute %s", __FUNCTION__, vp->da->name); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } done: @@ -625,7 +625,7 @@ static ssize_t encode_array(uint8_t *out, size_t outlen, if (!da->flags.length) { fr_strerror_printf("Can't encode array type attribute \"%s\" as it does not " "have a fixed length", da->name); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } element_len = da->flags.length; } else { @@ -698,14 +698,14 @@ static ssize_t encode_rfc_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const case FR_TYPE_STRUCTURAL: fr_strerror_printf("%s: Called with structural type %s", __FUNCTION__, fr_table_str_by_value(fr_value_box_type_table, tlv_stack[depth]->type, "?Unknown?")); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; default: if (((fr_dict_vendor_num_by_da(tlv_stack[depth]) == 0) && (tlv_stack[depth]->attr == 0)) || (tlv_stack[depth]->attr > 255)) { fr_strerror_printf("%s: Called with non-standard attribute %u", __FUNCTION__, tlv_stack[depth]->attr); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } break; } @@ -808,7 +808,7 @@ static inline ssize_t encode_tlv_internal(uint8_t *out, size_t outlen, */ if (!da->flags.extra && da->flags.subtype) { slen = encode_encrypted_value(value, end - value, value, p - value, encoder_ctx); - if (slen < 0) return PAIR_ENCODE_ERROR; + if (slen < 0) return PAIR_ENCODE_FATAL_ERROR; p = value + slen; } @@ -833,12 +833,12 @@ static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen, if (tlv_stack[depth]->type != FR_TYPE_TLV) { fr_strerror_printf("%s: Expected type \"tlv\" got \"%s\"", __FUNCTION__, fr_table_str_by_value(fr_value_box_type_table, tlv_stack[depth]->type, "?Unknown?")); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } if (!tlv_stack[depth + 1]) { fr_strerror_printf("%s: Can't encode empty TLV", __FUNCTION__); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } /* @@ -886,7 +886,7 @@ ssize_t fr_aka_sim_encode_pair(uint8_t *out, size_t outlen, fr_cursor_t *cursor, fr_dict_attr_t const *da = NULL; fr_aka_sim_encode_ctx_t *packet_ctx = encoder_ctx; - if (!cursor || !out) return PAIR_ENCODE_ERROR; + if (!cursor || !out) return PAIR_ENCODE_FATAL_ERROR; CHECK_FREESPACE(outlen, 4); /* Attributes lengths are always multiples of 4 */ @@ -898,7 +898,7 @@ ssize_t fr_aka_sim_encode_pair(uint8_t *out, size_t outlen, fr_cursor_t *cursor, if (vp->da->depth > FR_DICT_MAX_TLV_STACK) { fr_strerror_printf("%s: Attribute depth %i exceeds maximum nesting depth %i", __FUNCTION__, vp->da->depth, FR_DICT_MAX_TLV_STACK); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } if (vp->da->attr == FR_MAC) { @@ -950,7 +950,7 @@ ssize_t fr_aka_sim_encode_pair(uint8_t *out, size_t outlen, fr_cursor_t *cursor, */ if (fr_cursor_current(cursor) == vp) { fr_strerror_printf("%s: Nested attribute structure too large to encode", __FUNCTION__); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } return slen; @@ -979,7 +979,7 @@ ssize_t fr_aka_sim_encode(REQUEST *request, VALUE_PAIR *to_encode, void *encode_ vp = fr_pair_find_by_child_num(to_encode, packet_ctx->root, FR_SUBTYPE, TAG_ANY); if (!vp) { REDEBUG("Missing subtype attribute"); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } subtype = vp->vp_uint16; @@ -1044,7 +1044,7 @@ ssize_t fr_aka_sim_encode(REQUEST *request, VALUE_PAIR *to_encode, void *encode_ if (slen < 0) { error: talloc_free(buff); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } p += slen; rad_assert(p < end); /* We messed up a check somewhere in the encoder */ diff --git a/src/lib/io/pair.h b/src/lib/io/pair.h index 02a99a9849b..d8bcb6c1bcc 100644 --- a/src/lib/io/pair.h +++ b/src/lib/io/pair.h @@ -21,12 +21,37 @@ * @file io/pair.h * @brief Encoder/decoder library interface * - * @copyright 2017 The FreeRADIUS project + * @copyright 2017-2020 The FreeRADIUS project */ #include -#define PAIR_ENCODE_SKIP SSIZE_MIN + 1 -#define PAIR_ENCODE_ERROR SSIZE_MIN +/** @name Encoder errors + * @{ + */ + +/** Encoder skipped encoding an attribute + */ +#define PAIR_ENCODE_SKIPPED SSIZE_MIN + 1 + +/** Skipped encoding attribute + */ +#define PAIR_ENCODE_FATAL_ERROR SSIZE_MIN + +/** @} */ + +/** @name Decode errors + * @{ + */ + +/** Fatal error - Out of memory + */ +#define PAIR_DECODE_OOM SSIZE_MIN + 1 + +/** Fatal error - Failed decoding the packet + */ +#define PAIR_DECODE_FATAL_ERROR SSIZE_MIN + +/** @} */ /** Generic interface for encoding one or more VALUE_PAIRs * @@ -50,8 +75,8 @@ * @param[in] cursor Cursor containing the list of attributes to process. * @param[in] encoder_ctx Any encoder specific data such as secrets or configurables. * @return - * - PAIR_ENCODE_SKIP - The current pair is not valid for encoding and should be skipped. - * - PAIR_ENCODE_ERROR - Encoding failed in a fatal way. Encoding the packet should be + * - PAIR_ENCODE_SKIPPED - The current pair is not valid for encoding and should be skipped. + * - PAIR_ENCODE_FATAL_ERROR - Encoding failed in a fatal way. Encoding the packet should be * aborted in its entirety. * - <0 - The encoder ran out of space and returned the number of bytes as a negative * integer that would be required to encode the attribute. diff --git a/src/protocols/dhcpv6/base.c b/src/protocols/dhcpv6/base.c index 294d45e80b5..9b30a3c7780 100644 --- a/src/protocols/dhcpv6/base.c +++ b/src/protocols/dhcpv6/base.c @@ -566,7 +566,7 @@ ssize_t fr_dhcpv6_encode(uint8_t *packet, size_t packet_len, uint8_t const *orig while ((p < end) && (fr_cursor_current(&cursor) != NULL)) { slen = fr_dhcpv6_encode_option(p, end - p, &cursor, &packet_ctx); - if (slen == PAIR_ENCODE_SKIP) continue; + if (slen == PAIR_ENCODE_SKIPPED) continue; if (slen < 0) return slen - (p - packet); diff --git a/src/protocols/dhcpv6/decode.c b/src/protocols/dhcpv6/decode.c index db5d54ca016..c4295358c3d 100644 --- a/src/protocols/dhcpv6/decode.c +++ b/src/protocols/dhcpv6/decode.c @@ -274,7 +274,7 @@ static ssize_t decode_array(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_t cons if (!fr_cond_assert_msg(parent->flags.array, "%s: Internal sanity check failed, attribute \"%s\" does not have array bit set", - __FUNCTION__, parent->name)) return PAIR_ENCODE_ERROR; + __FUNCTION__, parent->name)) return PAIR_DECODE_FATAL_ERROR; /* * Fixed-size fields get decoded with a simple decoder. @@ -414,7 +414,7 @@ static ssize_t decode_tlvs(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_t const if (!fr_cond_assert_msg((parent->type == FR_TYPE_TLV || (parent->type == FR_TYPE_VENDOR)), "%s: Internal sanity check failed, attribute \"%s\" is not of type 'tlv'", - __FUNCTION__, parent->name)) return PAIR_ENCODE_ERROR; + __FUNCTION__, parent->name)) return PAIR_DECODE_FATAL_ERROR; p = data; end = data + data_len; @@ -449,7 +449,7 @@ static ssize_t decode_vsa(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_t const if (!fr_cond_assert_msg(parent->type == FR_TYPE_VSA, "%s: Internal sanity check failed, attribute \"%s\" is not of type 'vsa'", - __FUNCTION__, parent->name)) return PAIR_ENCODE_ERROR; + __FUNCTION__, parent->name)) return PAIR_DECODE_FATAL_ERROR; /* * Enterprise code plus at least one option header diff --git a/src/protocols/dhcpv6/encode.c b/src/protocols/dhcpv6/encode.c index 74dde11cd73..2b62a5771cb 100644 --- a/src/protocols/dhcpv6/encode.c +++ b/src/protocols/dhcpv6/encode.c @@ -142,12 +142,12 @@ static ssize_t encode_struct(uint8_t *out, size_t outlen, if (tlv_stack[depth]->type != FR_TYPE_STRUCT) { fr_strerror_printf("%s: Expected type \"struct\" got \"%s\"", __FUNCTION__, fr_table_str_by_value(fr_value_box_type_table, tlv_stack[depth]->type, "?Unknown?")); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } if (!tlv_stack[depth + 1]) { fr_strerror_printf("%s: Can't encode empty struct", __FUNCTION__); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } return fr_struct_to_network(out, outlen, tlv_stack, depth, cursor, encoder_ctx, encode_value); @@ -195,19 +195,19 @@ static ssize_t encode_value(uint8_t *out, size_t outlen, */ if (tlv_stack[depth + 1] != NULL) { fr_strerror_printf("%s: Encoding value but not at top of stack", __FUNCTION__); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } if (vp->da != da) { fr_strerror_printf("%s: Top of stack does not match vp->da", __FUNCTION__); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } switch (da->type) { case FR_TYPE_STRUCTURAL: fr_strerror_printf("%s: Called with structural type %s", __FUNCTION__, fr_table_str_by_value(fr_value_box_type_table, da->type, "?Unknown?")); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; default: break; @@ -240,7 +240,7 @@ static ssize_t encode_value(uint8_t *out, size_t outlen, /* * @todo - check for free space, etc. */ - if (slen <= 0) return PAIR_ENCODE_ERROR; + if (slen <= 0) return PAIR_ENCODE_FATAL_ERROR; /* * RFC 4704 says "FQDN", unless it's a @@ -393,7 +393,7 @@ static ssize_t encode_value(uint8_t *out, size_t outlen, case FR_TYPE_TIME_DELTA: CHECK_FREESPACE(outlen, fr_dhcpv6_option_len(vp)); slen = fr_value_box_to_network(NULL, p, end - p, &vp->data); - if (slen < 0) return PAIR_ENCODE_ERROR; + if (slen < 0) return PAIR_ENCODE_FATAL_ERROR; p += slen; break; @@ -439,9 +439,9 @@ static ssize_t encode_value(uint8_t *out, size_t outlen, while (fr_cursor_current(&child_cursor) != NULL) { child = fr_cursor_current(&child_cursor); slen = fr_dhcpv6_encode_option(p, end - p, &child_cursor, encoder_ctx); - if (slen == PAIR_ENCODE_SKIP) continue; + if (slen == PAIR_ENCODE_SKIPPED) continue; - if (slen < 0) return PAIR_ENCODE_ERROR; + if (slen < 0) return PAIR_ENCODE_FATAL_ERROR; if (slen == 0) break; p += slen; @@ -466,7 +466,7 @@ static ssize_t encode_value(uint8_t *out, size_t outlen, case FR_TYPE_MAX: fr_strerror_printf("Unsupported attribute type %s", fr_table_str_by_value(fr_value_box_type_table, da->type, "?Unknown?")); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } /* @@ -490,7 +490,7 @@ static inline ssize_t encode_array(uint8_t *out, size_t outlen, if (!fr_cond_assert_msg(da->flags.array, "%s: Internal sanity check failed, attribute \"%s\" does not have array bit set", - __FUNCTION__, da->name)) return PAIR_ENCODE_ERROR; + __FUNCTION__, da->name)) return PAIR_ENCODE_FATAL_ERROR; /* * DNS labels have internalized length, so we don't need @@ -507,7 +507,7 @@ static inline ssize_t encode_array(uint8_t *out, size_t outlen, * https://tools.ietf.org/html/rfc8415#section-10 */ slen = fr_dns_label_from_value_box(NULL, out, outlen, p, false, &vp->data); - if (slen <= 0) return PAIR_ENCODE_ERROR; + if (slen <= 0) return PAIR_ENCODE_FATAL_ERROR; p += slen; vp = next_encodable(cursor, encoder_ctx); @@ -537,7 +537,7 @@ static inline ssize_t encode_array(uint8_t *out, size_t outlen, slen = encode_value(p, end - p, tlv_stack, depth, cursor, encoder_ctx); if (slen < 0) return slen; - if (!fr_cond_assert(slen < UINT16_MAX)) return PAIR_ENCODE_ERROR; + if (!fr_cond_assert(slen < UINT16_MAX)) return PAIR_ENCODE_FATAL_ERROR; /* * Ensure we always create elements of the correct length. @@ -675,12 +675,12 @@ static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen, if (tlv_stack[depth]->type != FR_TYPE_TLV) { fr_strerror_printf("%s: Expected type \"tlv\" got \"%s\"", __FUNCTION__, fr_table_str_by_value(fr_value_box_type_table, tlv_stack[depth]->type, "?Unknown?")); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } if (!tlv_stack[depth + 1]) { fr_strerror_printf("%s: Can't encode empty TLV", __FUNCTION__); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } CHECK_FREESPACE(outlen, OPT_HDR_LEN); @@ -739,7 +739,7 @@ static ssize_t encode_vsio_hdr(uint8_t *out, size_t outlen, if (da->type != FR_TYPE_VSA) { fr_strerror_printf("%s: Expected type \"vsa\" got \"%s\"", __FUNCTION__, fr_table_str_by_value(fr_value_box_type_table, da->type, "?Unknown?")); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } /* @@ -757,7 +757,7 @@ static ssize_t encode_vsio_hdr(uint8_t *out, size_t outlen, if (dv->type != FR_TYPE_VENDOR) { fr_strerror_printf("%s: Expected type \"vsa\" got \"%s\"", __FUNCTION__, fr_table_str_by_value(fr_value_box_type_table, dv->type, "?Unknown?")); - return PAIR_ENCODE_ERROR; + return PAIR_ENCODE_FATAL_ERROR; } /* @@ -837,7 +837,7 @@ ssize_t fr_dhcpv6_encode_option(uint8_t *out, size_t outlen, fr_cursor_t *cursor if (vp->da->flags.internal) { fr_strerror_printf("Attribute \"%s\" is not a DHCPv6 option", vp->da->name); fr_cursor_next(cursor); - return PAIR_ENCODE_SKIP; + return PAIR_ENCODE_SKIPPED; } fr_proto_tlv_stack_build(tlv_stack, vp->da);