29RCSID(
"$Id: 8cc447c7d890b2870d66730ab44ea78371ef73f7 $")
31#include <freeradius-devel/server/base.h>
32#include <freeradius-devel/server/module_rlm.h>
33#include <freeradius-devel/server/map_proc.h>
34#include <freeradius-devel/util/base16.h>
35#include <freeradius-devel/util/debug.h>
36#include <freeradius-devel/util/sbuff.h>
37#include <freeradius-devel/util/types.h>
38#include <freeradius-devel/util/value.h>
39#include <freeradius-devel/unlang/xlat_func.h>
40#include <freeradius-devel/json/base.h>
43# error "rlm_json should not be built unless json-c is available"
89 request_t *request, fr_value_box_list_t *
in,
bool quote)
97 if (fr_value_box_list_num_elements(&in_head->vb_group) == 0) {
108 RPERROR(
"Failed creating escaped JSON value");
112 RPERROR(
"Failed assigning escaped JSON value to output box");
216 char *json_str = NULL;
224 sbuff =
FR_SBUFF_IN(in_head->vb_strvalue, in_head->vb_length);
245 .allow_wildcard =
true,
246 .dict_def = request->dict
263 RPEDEBUG(
"Error copying attributes");
306 REDEBUG(
"Failed to generate JSON string");
329 tmpl_t const *src, map_list_t
const *maps)
332 map_t const *map = NULL;
342 while ((map = map_list_next(maps, map))) {
346#ifndef HAVE_JSON_OBJECT_GET_INT64
348 cf_log_err(cp,
"64bit integers are not supported by linked json-c. "
349 "Upgrade to json-c >= 0.10 to use this feature");
354 switch (map->
rhs->type) {
367 cf_log_err(cp,
"Right side of map must be a string");
372 if (slen <= 0)
goto error;
384 if (map_list_next(maps, map)) {
405 map_t const *map,
void *uctx)
410 fr_value_box_list_t
head;
414 fr_value_box_list_init(&
head);
419 RPEDEBUG(
"Failed evaluating jpath");
422 if (ret == 0)
return 0;
425 for (
value = fr_value_box_list_head(&
head);
431 RPEDEBUG(
"Copying data to attribute failed");
455 fr_value_box_list_t *json, map_list_t
const *maps)
458 struct json_tokener *tok;
461 map_t const *map = NULL;
465 char const *json_str = NULL;
469 REDEBUG(
"JSON map input cannot be (null)");
477 REDEBUG(
"Failed concatenating input");
480 json_str = json_head->vb_strvalue;
482 if ((talloc_array_length(json_str) - 1) == 0) {
483 REDEBUG(
"JSON map input length must be > 0");
487 tok = json_tokener_new();
488 to_eval.
root = json_tokener_parse_ex(tok, json_str, (
int)(talloc_array_length(json_str) - 1));
490 REMARKER(json_str, tok->char_offset,
"%s", json_tokener_error_desc(json_tokener_get_error(tok)));
495 while ((map = map_list_next(maps, map))) {
496 switch (map->
rhs->type) {
521 RPERROR(
"Failed getting jpath data");
525 slen =
fr_jpath_parse(request, &node, to_parse, talloc_array_length(to_parse) - 1);
532 to_eval.
jpath = node;
548 json_object_put(to_eval.
root);
549 json_tokener_free(tok);
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
#define L(_str)
Helper for initialising arrays of string literals.
#define CONF_PARSER_TERMINATOR
#define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs)
conf_parser_t which populates a sub-struct using a CONF_SECTION
Defines a CONF_PAIR to C data type mapping.
Configuration AVP similar to a fr_pair_t.
A section grouping multiple CONF_PAIR.
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
#define cf_log_err(_cf, _fmt,...)
#define cf_canonicalize_error(_ci, _slen, _msg, _str)
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
static xlat_action_t json_quote_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Ensure contents are quoted correctly for a JSON document.
static xlat_action_t json_escape_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Ensure contents are escaped correctly for a JSON document.
static xlat_action_t json_encode_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Convert given attributes to a JSON document.
static xlat_action_t json_jpath_validate_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Determine if a jpath expression is valid.
Node in a jpath selector sequence.
char * fr_json_afrom_pair_list(TALLOC_CTX *ctx, fr_pair_list_t *vps, fr_json_format_t const *format)
Returns a JSON string of a list of value pairs.
char * fr_jpath_asprint(TALLOC_CTX *ctx, fr_jpath_node_t const *head)
Print a node list to a string for debugging.
struct fr_json_format_s fr_json_format_t
fr_slen_t fr_json_str_from_value(fr_sbuff_t *out, fr_value_box_t *vb, bool include_quotes)
Print a value box as its equivalent JSON format without going via a struct json_object (in most cases...
conf_parser_t const fr_json_format_config[]
int fr_jpath_evaluate_leaf(TALLOC_CTX *ctx, fr_value_box_list_t *out, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, json_object *root, fr_jpath_node_t const *jpath)
Evaluate a parsed jpath expression against a json-c tree.
ssize_t fr_jpath_escape_func(UNUSED request_t *request, char *out, size_t outlen, char const *in, UNUSED void *arg)
Escapes special chars.
void fr_json_version_print(void)
Print JSON-C version.
fr_table_num_sorted_t const fr_json_format_table[]
bool fr_json_format_verify(fr_json_format_t const *format, bool verbose)
Verify that the options in fr_json_format_t are valid.
ssize_t fr_jpath_parse(TALLOC_CTX *ctx, fr_jpath_node_t **head, char const *in, size_t inlen)
Parse a jpath string.
#define REMARKER(_str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
#define RPEDEBUG(fmt,...)
int map_to_request(request_t *request, map_t const *map, radius_map_getvalue_t func, void *ctx)
Convert map_t to fr_pair_t (s) and add them to a request_t.
int map_proc_register(TALLOC_CTX *ctx, void const *mod_inst, char const *name, map_proc_func_t evaluate, map_proc_instantiate_t instantiate, size_t inst_size, fr_value_box_safe_for_t literals_safe_for)
Register a map processor.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT64
64 Bit unsigned integer.
module_instance_t const * mi
Instance of the module being instantiated.
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for instantiation calls.
xlat_t * module_rlm_xlat_register(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
module_t common
Common fields presented by all modules.
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
int fr_pair_delete(fr_pair_list_t *list, fr_pair_t *vp)
Remove fr_pair_t from a list and free.
#define RETURN_MODULE_RCODE(_rcode)
#define RETURN_MODULE_FAIL
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_FAIL
Module failed, don't reply.
@ RLM_MODULE_UPDATED
OK (pairs modified).
fr_dict_attr_t const * request_attr_request
fr_json_format_t * format
fr_jpath_node_t * jpath
First node in jpath expression.
static xlat_arg_parser_t const json_escape_xlat_arg[]
static int mod_load(void)
static int mod_map_proc_instantiate(CONF_SECTION *cs, UNUSED void const *mod_inst, void *proc_inst, tmpl_t const *src, map_list_t const *maps)
Pre-parse and validate literal jpath expressions for maps.
static xlat_action_t json_escape(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in, bool quote)
static xlat_arg_parser_t const json_encode_xlat_arg[]
static int mod_bootstrap(module_inst_ctx_t const *mctx)
static void mod_unload(void)
rlm_json_jpath_cache_t * next
Next jpath cache entry.
fr_jpath_node_t const * jpath
static fr_sbuff_parse_rules_t const json_arg_parse_rules
static xlat_arg_parser_t const json_jpath_validate_xlat_arg[]
static int _json_map_proc_get_value(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, map_t const *map, void *uctx)
Converts a string value into a fr_pair_t.
static unlang_action_t mod_map_proc(rlm_rcode_t *p_result, UNUSED void const *mod_inst, void *proc_inst, request_t *request, fr_value_box_list_t *json, map_list_t const *maps)
Parses a JSON string, and executes jpath queries against it to map values to attributes.
static int mod_instantiate(module_inst_ctx_t const *mctx)
static conf_parser_t const module_config[]
static int instantiate(module_inst_ctx_t const *mctx)
int fr_sbuff_reset_talloc(fr_sbuff_t *sbuff)
Reset a talloced buffer to its initial length, clearing any data stored.
bool fr_sbuff_next_if_char(fr_sbuff_t *sbuff, char c)
Return true if the current char matches, and if it does, advance.
#define fr_sbuff_start(_sbuff_or_marker)
#define fr_sbuff_set(_dst, _src)
#define FR_SBUFF_IN(_start, _len_or_end)
#define fr_sbuff_adv_past_whitespace(_sbuff, _len, _tt)
#define FR_SBUFF_TERMS(...)
Initialise a terminal structure with a list of sorted strings.
#define fr_sbuff_extend(_sbuff_or_marker)
#define fr_sbuff_used(_sbuff_or_marker)
#define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
CONF_SECTION * conf
Module's instance configuration.
void * data
Module's instance data.
void * boot
Data allocated during the boostrap phase.
conf_parser_t const * config
How to convert a CONF_SECTION to a module instance.
#define tmpl_value_length(_tmpl)
#define tmpl_value(_tmpl)
#define tmpl_is_attr(vpt)
@ TMPL_TYPE_DATA
Value in native boxed format.
@ TMPL_TYPE_DATA_UNRESOLVED
Unparsed literal string.
int tmpl_copy_pairs(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, tmpl_t const *vpt))
Copy pairs matching a tmpl_t in the current request_t.
ssize_t tmpl_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err, tmpl_t **out, fr_sbuff_t *name, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Parse a string into a TMPL_TYPE_ATTR_* type tmpl_t.
#define tmpl_value_type(_tmpl)
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
#define tmpl_aexpand(_ctx, _out, _request, _vpt, _escape, _escape_ctx)
Expand a tmpl to a C type, allocing a new buffer to hold the string.
Optional arguments passed to vp_tmpl functions.
eap_aka_sim_process_conf_t * inst
tmpl_t * lhs
Typically describes the attribute to add, modify or compare.
tmpl_t * rhs
Typically describes a literal value or a src attribute to copy or compare.
CONF_ITEM * ci
Config item that the map was created from.
Stores an attribute, a value and various bits of other data.
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
#define talloc_get_type_abort_const
fr_type_t type
Type to cast argument to.
bool required
Argument must be present, and non-empty.
#define XLAT_ARG_PARSER_TERMINATOR
@ XLAT_ACTION_FAIL
An xlat function failed.
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition for a single argument consumend by an xlat function.
fr_pair_t * fr_pair_list_next(fr_pair_list_t const *list, fr_pair_t const *item))
Get the next item in a valuepair list after a specific entry.
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
void fr_pair_list_append(fr_pair_list_t *dst, fr_pair_list_t *src)
Appends a list of fr_pair_t from a temporary list to a destination list.
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
char const * fr_strerror(void)
Get the last library error.
int fr_value_box_asprintf(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, bool tainted, char const *fmt,...)
Print a formatted string using our internal printf wrapper and assign it to a value box.
int fr_value_box_strdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Copy a nul terminated string to a fr_value_box_t.
int fr_value_box_steal(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t *src)
Copy value data verbatim moving any buffers to the specified context.
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Copy a string to to a fr_value_box_t.
int fr_value_box_bstrdup_buffer_shallow(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Assign a talloced buffer containing a nul terminated string to a box, but don't copy it.
int fr_value_box_list_concat_in_place(TALLOC_CTX *ctx, fr_value_box_t *out, fr_value_box_list_t *list, fr_type_t type, fr_value_box_list_action_t proc_action, bool flatten, size_t max_size)
Concatenate a list of value boxes.
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
#define fr_value_box_list_foreach(_list_head, _iter)
int format(printf, 5, 0))
static size_t char ** out
module_ctx_t const * mctx
Synthesised module calling ctx.
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
xlat_t * xlat_func_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function.
void xlat_func_unregister(char const *name)
Unregister an xlat function.