]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
pair: Establish error codes for decoders
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 6 Mar 2020 21:48:24 +0000 (15:48 -0600)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 6 Mar 2020 21:48:24 +0000 (15:48 -0600)
src/lib/eap_aka_sim/encode.c
src/lib/io/pair.h
src/protocols/dhcpv6/base.c
src/protocols/dhcpv6/decode.c
src/protocols/dhcpv6/encode.c

index e38e3b58472d4227f4bb4617689bc7bf5b1d90bd..df07eaa10d51f391fa697073eebd7d2f04899597 100644 (file)
@@ -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 */
index 02a99a9849b0a144ab8f99a4e23ebd8c08fd3e8a..d8bcb6c1bcc7263b4419768f286c6e46b57084f8 100644 (file)
  * @file io/pair.h
  * @brief Encoder/decoder library interface
  *
- * @copyright 2017 The FreeRADIUS project
+ * @copyright 2017-2020 The FreeRADIUS project
  */
 #include <freeradius-devel/util/value.h>
 
-#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.
index 294d45e80b5d1f576d8612b2fbe34fa7f53f1e0c..9b30a3c77807be11f49f3687c4df9041e6772713 100644 (file)
@@ -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);
 
index db5d54ca0162713cda10b91319f996a647472b8d..c4295358c3d98f5b4feb0db638acc98846d00ad4 100644 (file)
@@ -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
index 74dde11cd7379012b86aee2d939254575b1ab487..2b62a5771cbc5467f16c611949273e721c2a9c2f 100644 (file)
@@ -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);