From: Arran Cudbard-Bell Date: Wed, 23 May 2018 13:09:30 +0000 (+0600) Subject: Split the cast operation out of fr_json_object_to_value_box X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=11a8ce1b4b8a456734ae44c540e111e1daeba576;p=thirdparty%2Ffreeradius-server.git Split the cast operation out of fr_json_object_to_value_box --- diff --git a/src/modules/rlm_json/jpath.c b/src/modules/rlm_json/jpath.c index d6dbb100731..9e7c2f8e3da 100644 --- a/src/modules/rlm_json/jpath.c +++ b/src/modules/rlm_json/jpath.c @@ -338,7 +338,7 @@ static int jpath_evaluate(TALLOC_CTX *ctx, fr_value_box_t ***tail, case JPATH_SELECTOR_ROOT: case JPATH_SELECTOR_CURRENT: rad_assert(0); - return -1; /* Not yet implemented */ + return -1; /* Not yet implemented */ } /* @@ -346,11 +346,17 @@ static int jpath_evaluate(TALLOC_CTX *ctx, fr_value_box_t ***tail, * we now attempt conversion of the leaf to * the specified value. */ - value = talloc_zero(ctx, fr_value_box_t); - if (fr_json_object_to_value_box(value, value, object, dst_type, dst_enumv) < 0) { + value = fr_value_box_alloc_null(ctx); + if (fr_json_object_to_value_box(value, value, object, dst_enumv, true) < 0) { talloc_free(value); return -1; } + + if (fr_value_box_cast_in_place(value, value, dst_type, dst_enumv) < 0) { + talloc_free(value); + return -1; + } + **tail = value; *tail = &(**tail)->next; return 1; diff --git a/src/modules/rlm_json/json.c b/src/modules/rlm_json/json.c index 24cbd4cb171..7a2d34f1ce4 100644 --- a/src/modules/rlm_json/json.c +++ b/src/modules/rlm_json/json.c @@ -31,31 +31,54 @@ /** Convert json object to fr_value_box_t * * @param[in] ctx to allocate any value buffers in (should usually be the same as out). - * @param[in] out Where to write value_box. + * @param[in] out Where to write value. Must be initialised. * @param[in] object to convert. - * @param[in] dst_type FreeRADIUS type to convert to. - * @param[in] dst_enumv Enumeration values to allow string to integer conversions. + * @param[in] enumv Any string values are assumed to be in PRESENTATION format, meaning + * that if an enumv is specified, they'll be checked against the list + * of aliases for that enumeration, and possibly converted into one of + * the enumeration values (which may not be a string). + * @param[in] tainted Whether the data source is untrusted. * @return * - 0 on success. * - -1 on failure. */ int fr_json_object_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *out, json_object *object, - fr_type_t dst_type, fr_dict_attr_t const *dst_enumv) + fr_dict_attr_t const *enumv, bool tainted) { - fr_value_box_t in; - - memset(&in, 0, sizeof(in)); - switch (fr_json_object_get_type(object)) { case json_type_string: - in.type = FR_TYPE_STRING; - in.vb_strvalue = json_object_get_string(object); - in.datum.length = json_object_get_string_len(object); + { + char const *value; + size_t len; + fr_dict_enum_t *found; + + value = json_object_get_string(object); + len = json_object_get_string_len(object); + + if (!enumv) goto no_enumv; + + if (fr_dict_valid_name(value, len) < 0) goto no_enumv; + + /* + * If an alias exists, use that value instead + */ + found = fr_dict_enum_by_alias(enumv, value, len); + if (found) { + if (fr_value_box_copy(ctx, out, found->value) < 0) return -1; + return 0; + } + + no_enumv: + /* + * Just copy the string to the box. + */ + fr_value_box_bstrndup(ctx, out, NULL, value, len, tainted); + } break; case json_type_double: - in.type = FR_TYPE_FLOAT64; - in.vb_float64 = json_object_get_double(object); + out->type = FR_TYPE_FLOAT64; + out->vb_float64 = json_object_get_double(object); break; case json_type_int: @@ -78,50 +101,52 @@ int fr_json_object_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *out, json_objec #else num = json_object_get_int64(object); if (num < INT32_MIN) { /* 64bit signed*/ - in.type = FR_TYPE_INT64; - in.vb_int64 = (int64_t) num; + out->type = FR_TYPE_INT64; + out->vb_int64 = (int64_t) num; } else if (num > UINT32_MAX) { /* 64bit unsigned */ - in.type = FR_TYPE_UINT64; - in.vb_uint64 = (uint64_t) num; + out->type = FR_TYPE_UINT64; + out->vb_uint64 = (uint64_t) num; } else #endif if (num < INT16_MIN) { /* 32bit signed */ - in.type = FR_TYPE_INT32; - in.vb_int32 = (int32_t)num; + out->type = FR_TYPE_INT32; + out->vb_int32 = (int32_t)num; } else if (num < INT8_MIN) { /* 16bit signed */ - in.type = FR_TYPE_INT16; - in.vb_int16 = (int16_t)num; + out->type = FR_TYPE_INT16; + out->vb_int16 = (int16_t)num; } else if (num < 0) { /* 8bit signed */ - in.type = FR_TYPE_INT8; - in.vb_int8 = (int8_t)num; + out->type = FR_TYPE_INT8; + out->vb_int8 = (int8_t)num; } else if (num > UINT16_MAX) { /* 32bit unsigned */ - in.type = FR_TYPE_UINT32; - in.vb_uint32 = (uint32_t) num; + out->type = FR_TYPE_UINT32; + out->vb_uint32 = (uint32_t) num; } else if (num > UINT8_MAX) { /* 16bit unsigned */ - in.type = FR_TYPE_UINT16; - in.vb_uint16 = (uint16_t) num; + out->type = FR_TYPE_UINT16; + out->vb_uint16 = (uint16_t) num; } else { /* 8bit unsigned */ - in.type = FR_TYPE_UINT8; - in.vb_uint8 = (uint8_t) num; + out->type = FR_TYPE_UINT8; + out->vb_uint8 = (uint8_t) num; } } break; case json_type_boolean: - in.type = FR_TYPE_BOOL; - in.datum.boolean = json_object_get_boolean(object); + out->type = FR_TYPE_BOOL; + out->datum.boolean = json_object_get_boolean(object); break; case json_type_null: case json_type_array: case json_type_object: - in.type = FR_TYPE_STRING; - in.vb_strvalue = json_object_to_json_string(object); - in.datum.length = strlen(in.vb_strvalue); + { + char const *value = json_object_to_json_string(object); + + fr_value_box_bstrndup(ctx, out, NULL, value, strlen(value), tainted); + } break; } - if (fr_value_box_cast(ctx, out, dst_type, dst_enumv, &in) < 0) return -1; + out->tainted = tainted; return 0; } @@ -133,6 +158,18 @@ int fr_json_object_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *out, json_objec */ json_object *json_object_from_value_box(TALLOC_CTX *ctx, fr_value_box_t const *data) { + /* + * We're converting to PRESENTATION format + * so any attributes with enumeration values + * should be converted to string types. + */ + if (data->enumv) { + fr_dict_enum_t *enumv; + + enumv = fr_dict_enum_by_value(data->enumv, data); + if (enumv) return json_object_new_string(enumv->alias); + } + switch (data->type) { default: do_string: diff --git a/src/modules/rlm_json/json.h b/src/modules/rlm_json/json.h index 8309ad8a20f..80c23e12bf0 100644 --- a/src/modules/rlm_json/json.h +++ b/src/modules/rlm_json/json.h @@ -58,7 +58,7 @@ ssize_t fr_jpath_parse(TALLOC_CTX *ctx, fr_jpath_node_t **head, char const *in, /* json.c */ int fr_json_object_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *out, json_object *object, - fr_type_t dst_type, fr_dict_attr_t const *dst_enumv); + fr_dict_attr_t const *enumv, bool tainted); json_object *json_object_from_value_box(TALLOC_CTX *ctx, fr_value_box_t const *data);