The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
rlm_json.c
Go to the documentation of this file.
1/*
2 * This program is is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or (at
5 * your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: ed81482a865f676c71506eb5807eb2c3748891c3 $
19 * @file rlm_json.c
20 * @brief Parses JSON responses
21 *
22 * @author Arran Cudbard-Bell
23 * @author Matthew Newton
24 *
25 * @copyright 2015 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
26 * @copyright 2015,2020 Network RADIUS SAS (legal@networkradius.com)
27 * @copyright 2015 The FreeRADIUS Server Project
28 */
29RCSID("$Id: ed81482a865f676c71506eb5807eb2c3748891c3 $")
30
31#include <freeradius-devel/server/base.h>
32#include <freeradius-devel/server/module_rlm.h>
33#include <freeradius-devel/util/base16.h>
34#include <freeradius-devel/util/base64.h>
35#include <freeradius-devel/unlang/xlat_func.h>
36#include <freeradius-devel/json/base.h>
37
38#ifndef HAVE_JSON
39# error "rlm_json should not be built unless json-c is available"
40#endif
41
42static fr_sbuff_parse_rules_t const json_arg_parse_rules = {
43 .terminals = &FR_SBUFF_TERMS(
44 L("\t"),
45 L(" "),
46 L("!")
47 )
48};
49
50/** rlm_json module instance
51 *
52 */
53typedef struct {
56
57
58static conf_parser_t const module_config[] = {
60 .subcs_size = sizeof(fr_json_format_t), .subcs_type = "fr_json_format_t" },
61
63};
64
65/** Forms a linked list of jpath head node pointers (a list of jpaths)
66 */
69 fr_jpath_node_t *jpath; //!< First node in jpath expression.
70 rlm_json_jpath_cache_t *next; //!< Next jpath cache entry.
71};
72
73typedef struct {
75 json_object *root;
77
82
83static xlat_action_t json_escape(TALLOC_CTX *ctx, fr_dcursor_t *out,
84 xlat_ctx_t const *xctx,
85 request_t *request, fr_value_box_list_t *in, bool quote)
86{
88 fr_json_format_t const *format = inst->format;
89 fr_value_box_t *vb_out;
90 fr_value_box_t *in_head = fr_value_box_list_head(in);
91 fr_sbuff_t *agg;
92
93 FR_SBUFF_TALLOC_THREAD_LOCAL(&agg, 1024, SIZE_MAX);
94
95 if (fr_value_box_list_num_elements(&in_head->vb_group) == 0) {
96 MEM(vb_out = fr_value_box_alloc_null(ctx));
97 fr_value_box_strdup(vb_out, vb_out, NULL, "null", false);
98 fr_dcursor_append(out, vb_out);
99
100 return XLAT_ACTION_DONE;
101 }
102
103 fr_value_box_list_foreach(&in_head->vb_group, vb_in) {
104 fr_value_box_t *vb_to_encode = vb_in;
106 fr_slen_t slen;
107
108 if (format) {
109 /*
110 * Encode octets as base16 or base64 when requested.
111 */
112 if ((vb_in->type == FR_TYPE_OCTETS) &&
113 (format->value.binary_format != JSON_BINARY_FORMAT_RAW)) {
114 MEM(vb_out = fr_value_box_alloc_null(ctx));
115 if (quote) fr_sbuff_in_char(agg, '"');
116 switch (format->value.binary_format) {
117 /*
118 * Hex encode octets values when requested.
119 */
121 fr_base16_encode(agg, &FR_DBUFF_TMP(vb_in->vb_octets, vb_in->vb_length));
122 break;
123
124 /*
125 * Base64-encode octets values when requested.
126 */
128 fr_base64_encode(agg, &FR_DBUFF_TMP(vb_in->vb_octets, vb_in->vb_length), true);
129 break;
130
131 default:
132 fr_assert(0); /* ENUM updated and no encode() function */
133 break;
134 }
135 if (quote) fr_sbuff_in_char(agg, '"');
136 goto assign;
137 }
138
139 /*
140 * Cast to string when always_string is set.
141 */
142 if (format->value.always_string && (vb_in->type != FR_TYPE_STRING)) {
143 if (unlikely(fr_value_box_cast(ctx, &vb_str, FR_TYPE_STRING, NULL, vb_to_encode) < 0)) {
144 RPERROR("Failed casting value to string");
145 return XLAT_ACTION_FAIL;
146 }
147 vb_to_encode = &vb_str;
148 }
149 }
150
151 MEM(vb_out = fr_value_box_alloc_null(ctx));
152 slen = fr_json_str_from_value(agg, vb_to_encode, quote);
153 fr_value_box_clear(&vb_str);
154 if (slen < 0) {
155 RPERROR("Failed creating escaped JSON value");
156 return XLAT_ACTION_FAIL;
157 }
158
159 assign:
160 if (fr_value_box_bstrndup(vb_out, vb_out, NULL, fr_sbuff_start(agg), fr_sbuff_used(agg), vb_in->tainted) < 0) {
161 RPERROR("Failed assigning escaped JSON value to output box");
162 return XLAT_ACTION_FAIL;
163 }
165 fr_dcursor_append(out, vb_out);
166 }
167
168 return XLAT_ACTION_DONE;
169}
170/** Ensure contents are escaped correctly for a JSON document
171 *
172 * This allows values to be embedded inside JSON strings.
173 *
174 * @ingroup xlat_functions
175 *
176 */
178 xlat_ctx_t const *xctx,
179 request_t *request, fr_value_box_list_t *in)
180{
181 return json_escape(ctx, out, xctx, request, in, false);
182}
183
185 { .required = true, .concat = true, .type = FR_TYPE_STRING },
187};
188
189/** Ensure contents are quoted correctly for a JSON document
190 *
191 * This emits values with escaping, and appropriate quoting '"' depending on the
192 * type of values being produced. This lets boxed values be inserted directly
193 * as table values and array elements, without needing to determine if the
194 * expansion needs to be wrapped in quotes.
195 *
196 * @ingroup xlat_functions
197 *
198 */
200 xlat_ctx_t const *xctx,
201 request_t *request, fr_value_box_list_t *in)
202{
203 return json_escape(ctx, out, xctx, request, in, true);
204}
205
206/** Determine if a jpath expression is valid
207 *
208 * @ingroup xlat_functions
209 *
210 * Writes the output (in the format @verbatim<bytes parsed>[:error]@endverbatim).
211 */
213 UNUSED xlat_ctx_t const *xctx,
214 request_t *request, fr_value_box_list_t *in)
215{
216 fr_value_box_t *path = fr_value_box_list_head(in);
218 ssize_t slen;
219 char *jpath_str;
220 fr_value_box_t *vb;
221
222 MEM(vb = fr_value_box_alloc_null(ctx));
223
224 slen = fr_jpath_parse(request, &head, path->vb_strvalue, path->vb_length);
225 if (slen <= 0) {
226 fr_value_box_asprintf(ctx, vb, NULL, false, "%zu:%s", -(slen), fr_strerror());
228 fr_assert(head == NULL);
229 return XLAT_ACTION_DONE;
230 }
231 fr_assert(talloc_get_type_abort(head, fr_jpath_node_t));
232
233 jpath_str = fr_jpath_asprint(request, head);
234
235 fr_value_box_asprintf(ctx, vb, NULL, false, "%zu:%s", (size_t) slen, jpath_str);
238 talloc_free(jpath_str);
239
240 return XLAT_ACTION_DONE;
241}
242
244 { .single = true, .type = FR_TYPE_STRING, .required = true },
245 { .single = true, .type = FR_TYPE_STRING, .variadic = XLAT_ARG_VARIADIC_EMPTY_SQUASH },
247};
248
249/** Convert given attributes to a JSON document
250 *
251 * Usage is `%json.encode('attr', 'list[*]', '!negation)`
252 *
253 * @ingroup xlat_functions
254 */
256 xlat_ctx_t const *xctx,
257 request_t *request, fr_value_box_list_t *in)
258{
260 fr_json_format_t const *format = inst->format;
261
262 ssize_t slen;
263 tmpl_t *vpt = NULL;
264 fr_pair_list_t json_vps, vps;
265 bool negate;
266 char *json_str = NULL;
267 fr_value_box_t *vb;
268 fr_sbuff_t sbuff;
269
270 fr_pair_list_init(&json_vps);
271 fr_pair_list_init(&vps);
272
273 /*
274 * Iterate through the list of attribute templates in the xlat. For each
275 * one we either add it to the list of attributes for the JSON document
276 * or, if prefixed with '!', remove from the JSON list.
277 */
279 sbuff = FR_SBUFF_IN(ref->vb_strvalue, ref->vb_length);
280 fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX, NULL);
281 negate = false;
282
283 /* Check if we should be removing attributes */
284 if (fr_sbuff_next_if_char(&sbuff, '!')) negate = true;
285
286 /* Decode next attr template */
287 slen = tmpl_afrom_attr_substr(ctx, NULL, &vpt,
288 &sbuff,
290 &(tmpl_rules_t){
291 .attr = {
292 .list_def = request_attr_request,
293 .allow_wildcard = true,
294 .dict_def = request->local_dict,
295 }
296 });
297 if (slen <= 0) {
298 fr_sbuff_set(&sbuff, (size_t)(slen * -1));
299 REMARKER(fr_sbuff_start(&sbuff), fr_sbuff_used(&sbuff), "%s", fr_strerror());
300 error:
301 fr_pair_list_free(&json_vps);
303 return XLAT_ACTION_FAIL;
304 }
305
306 /*
307 * Get attributes from the template.
308 * Missing attribute isn't an error (so -1, not 0).
309 */
310 if (tmpl_copy_pairs(ctx, &vps, request, vpt) < -1) {
311 RPEDEBUG("Error copying attributes");
312 goto error;
313 }
314
315 if (negate) {
316 /* Remove all template attributes from JSON list */
317 for (fr_pair_t *vp = fr_pair_list_head(&vps);
318 vp;
319 vp = fr_pair_list_next(&vps, vp)) {
320
321 fr_pair_t *vpm = fr_pair_list_head(&json_vps);
322 while (vpm) {
323 if (vp->da == vpm->da) {
324 fr_pair_t *next = fr_pair_list_next(&json_vps, vpm);
325 fr_pair_delete(&json_vps, vpm);
326 vpm = next;
327 continue;
328 }
329 vpm = fr_pair_list_next(&json_vps, vpm);
330 }
331 }
332
333 fr_pair_list_free(&vps);
334 } else {
335 /* Add template VPs to JSON list */
336 fr_pair_list_append(&json_vps, &vps);
337 }
338
339 TALLOC_FREE(vpt);
340 }
341
342 /*
343 * Given the list of attributes we now have in json_vps,
344 * convert them into a JSON document and append it to the
345 * return cursor.
346 */
347 MEM(vb = fr_value_box_alloc_null(ctx));
348
349 json_str = fr_json_afrom_pair_list(vb, &json_vps, format);
350 if (!json_str) {
351 REDEBUG("Failed to generate JSON string");
352 goto error;
353 }
354 fr_value_box_bstrdup_buffer_shallow(NULL, vb, NULL, json_str, false);
355
357 fr_pair_list_free(&json_vps);
358
359 return XLAT_ACTION_DONE;
360}
361
362/** Pre-parse and validate literal jpath expressions for maps
363 *
364 * @param[in] cs #CONF_SECTION that defined the map instance.
365 * @param[in] mod_inst module instance (unused).
366 * @param[in] proc_inst the cache structure to fill.
367 * @param[in] src Where to get the JSON data from.
368 * @param[in] maps set of maps to translate to jpaths.
369 * @return
370 * - 0 on success.
371 * - -1 on failure.
372 */
373static int mod_map_proc_instantiate(CONF_SECTION *cs, UNUSED void const *mod_inst, void *proc_inst,
374 tmpl_t const *src, map_list_t const *maps)
375{
376 rlm_json_jpath_cache_t *cache_inst = proc_inst;
377 map_t const *map = NULL;
378 ssize_t slen;
379 rlm_json_jpath_cache_t *cache = cache_inst, **tail = &cache->next;
380
381 if (!src) {
382 cf_log_err(cs, "Missing JSON source");
383
384 return -1;
385 }
386
387 while ((map = map_list_next(maps, map))) {
388 CONF_PAIR *cp = cf_item_to_pair(map->ci);
389 char const *p;
390
391#ifndef HAVE_JSON_OBJECT_GET_INT64
392 if (tmpl_is_attr(map->lhs) && (tmpl_attr_tail_da(map->lhs)->type == FR_TYPE_UINT64)) {
393 cf_log_err(cp, "64bit integers are not supported by linked json-c. "
394 "Upgrade to json-c >= 0.10 to use this feature");
395 return -1;
396 }
397#endif
398
399 switch (map->rhs->type) {
401 p = map->rhs->name;
402 slen = fr_jpath_parse(cache, &cache->jpath, p, map->rhs->len);
403 if (slen <= 0) {
404 error:
405 cf_canonicalize_error(cp, slen, "Syntax error", fr_strerror());
406 return -1;
407 }
408 break;
409
410 case TMPL_TYPE_DATA:
411 if (tmpl_value_type(map->rhs) != FR_TYPE_STRING) {
412 cf_log_err(cp, "Right side of map must be a string");
413 return -1;
414 }
415 p = tmpl_value(map->rhs)->vb_strvalue;
416 slen = fr_jpath_parse(cache, &cache->jpath, p, tmpl_value_length(map->rhs));
417 if (slen <= 0) goto error;
418 break;
419
420 default:
421 continue;
422 }
423
424 /*
425 * Slightly weird... This is here because our first
426 * list member was pre-allocated and passed to the
427 * instantiation callback.
428 */
429 if (map_list_next(maps, map)) {
430 *tail = cache = talloc_zero(cache, rlm_json_jpath_cache_t);
431 tail = &cache->next;
432 }
433 }
434
435 return 0;
436}
437
438/** Converts a string value into a #fr_pair_t
439 *
440 * @param[in,out] ctx to allocate #fr_pair_t (s).
441 * @param[out] out where to write the resulting #fr_pair_t.
442 * @param[in] request The current request.
443 * @param[in] map to process.
444 * @param[in] uctx The json tree/jpath expression to evaluate.
445 * @return
446 * - 0 on success.
447 * - -1 on failure.
448 */
449static int _json_map_proc_get_value(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request,
450 map_t const *map, void *uctx)
451{
452 fr_pair_t *vp;
453 rlm_json_jpath_to_eval_t *to_eval = uctx;
455 fr_value_box_list_t head;
456 int ret;
457
459 fr_value_box_list_init(&head);
460
461 ret = fr_jpath_evaluate_leaf(request, &head, tmpl_attr_tail_da(map->lhs)->type, tmpl_attr_tail_da(map->lhs),
462 to_eval->root, to_eval->jpath);
463 if (ret < 0) {
464 RPEDEBUG("Failed evaluating jpath");
465 return -1;
466 }
467 if (ret == 0) return 0;
468 fr_assert(!fr_value_box_list_empty(&head));
469
470 for (value = fr_value_box_list_head(&head);
471 value;
472 fr_pair_append(out, vp), value = fr_value_box_list_next(&head, value)) {
474
475 if (fr_value_box_steal(vp, &vp->data, value) < 0) {
476 RPEDEBUG("Copying data to attribute failed");
479 return -1;
480 }
481 }
482
483 return 0;
484}
485
486/** Parses a JSON string, and executes jpath queries against it to map values to attributes
487 *
488 * @param p_result Result of applying map:
489 * - #RLM_MODULE_NOOP no rows were returned or columns matched.
490 * - #RLM_MODULE_UPDATED if one or more #fr_pair_t were added to the #request_t.
491 * - #RLM_MODULE_FAIL if a fault occurred.
492 * @param mpctx Call context for the map processor, containing the jpath cache.
493 * @param request The current request.
494 * @param json JSON string to parse.
495 * @param maps Head of the map list.
496 * @return UNLANG_ACTION_CALCULATE_RESULT
497 */
498static unlang_action_t mod_map_proc(unlang_result_t *p_result, map_ctx_t const *mpctx, request_t *request,
499 fr_value_box_list_t *json, map_list_t const *maps)
500{
502 struct json_tokener *tok;
503
504 rlm_json_jpath_cache_t const *cache = mpctx->mpi;
505 map_t const *map = NULL;
506
508
509 char const *json_str = NULL;
510 fr_value_box_t *json_head = fr_value_box_list_head(json);
511
512 if (!json_head) {
513 REDEBUG("JSON map input cannot be (null)");
515 }
516
518 json_head, json, FR_TYPE_STRING,
520 SIZE_MAX) < 0) {
521 REDEBUG("Failed concatenating input");
523 }
524 json_str = json_head->vb_strvalue;
525
526 if ((talloc_strlen(json_str)) == 0) {
527 REDEBUG("JSON map input length must be > 0");
529 }
530
531 tok = json_tokener_new();
532 to_eval.root = json_tokener_parse_ex(tok, json_str, (int)(talloc_strlen(json_str)));
533 if (!to_eval.root) {
534 REMARKER(json_str, tok->char_offset, "%s", json_tokener_error_desc(json_tokener_get_error(tok)));
535 rcode = RLM_MODULE_FAIL;
536 goto finish;
537 }
538
539 while ((map = map_list_next(maps, map))) {
540 switch (map->rhs->type) {
541 /*
542 * Cached types
543 */
545 case TMPL_TYPE_DATA:
546 to_eval.jpath = cache->jpath;
547
548 if (map_to_request(request, map, _json_map_proc_get_value, &to_eval) < 0) {
549 rcode = RLM_MODULE_FAIL;
550 goto finish;
551 }
552 cache = cache->next;
553 break;
554
555 /*
556 * Dynamic types
557 */
558 default:
559 {
560 ssize_t slen;
561 fr_jpath_node_t *node;
562 char *to_parse;
563
564 if (tmpl_aexpand(request, &to_parse, request, map->rhs, fr_jpath_escape_func, NULL) < 0) {
565 RPERROR("Failed getting jpath data");
566 rcode = RLM_MODULE_FAIL;
567 goto finish;
568 }
569 slen = fr_jpath_parse(request, &node, to_parse, talloc_strlen(to_parse));
570 if (slen <= 0) {
571 REMARKER(to_parse, -(slen), "%s", fr_strerror());
572 talloc_free(to_parse);
573 rcode = RLM_MODULE_FAIL;
574 goto finish;
575 }
576 to_eval.jpath = node;
577
578 if (map_to_request(request, map, _json_map_proc_get_value, &to_eval) < 0) {
579 talloc_free(node);
580 talloc_free(to_parse);
581 rcode = RLM_MODULE_FAIL;
582 goto finish;
583 }
584 talloc_free(node);
585 }
586 break;
587 }
588 }
589
590
591finish:
592 json_object_put(to_eval.root);
593 json_tokener_free(tok);
594
595 RETURN_UNLANG_RCODE(rcode);
596}
597
598static int mod_instantiate(module_inst_ctx_t const *mctx)
599{
600 rlm_json_t const *inst = talloc_get_type_abort(mctx->mi->data, rlm_json_t);
601 CONF_SECTION *conf = mctx->mi->conf;
602 fr_json_format_t *format = inst->format;
603
604 /*
605 * Check the output format type and warn on unused
606 * format options
607 */
609 if (format->output_mode == JSON_MODE_UNSET) {
610 cf_log_err(conf, "output_mode value \"%s\" is invalid", format->output_mode_str);
611 return -1;
612 }
614
615 return 0;
616}
617
618static int mod_bootstrap(module_inst_ctx_t const *mctx)
619{
620 rlm_json_t const *inst = talloc_get_type_abort(mctx->mi->data, rlm_json_t);
621 xlat_t *xlat;
622
623 xlat = module_rlm_xlat_register(mctx->mi->boot, mctx, "encode", json_encode_xlat, FR_TYPE_STRING);
625
626 xlat = module_rlm_xlat_register(mctx->mi->boot, mctx, "escape", json_escape_xlat, FR_TYPE_STRING);
628
629 xlat = module_rlm_xlat_register(mctx->mi->boot, mctx, "quote", json_quote_xlat, FR_TYPE_STRING);
631
632 if (map_proc_register(mctx->mi->boot, inst, "json", mod_map_proc,
634 return 0;
635}
636
637static int mod_load(void)
638{
639 xlat_t *xlat;
640
642
643 if (unlikely(!(xlat = xlat_func_register(NULL, "json.jpath_validate", json_jpath_validate_xlat, FR_TYPE_STRING)))) return -1;
645
646 return 0;
647}
648
649static void mod_unload(void)
650{
651 xlat_func_unregister("json.jpath_validate");
652}
653
654/*
655 * The module name should be the only globally exported symbol.
656 * That is, everything else should be 'static'.
657 *
658 * If the module needs to temporarily modify it's instantiation
659 * data, the type should be changed to MODULE_TYPE_THREAD_UNSAFE.
660 * The server will then take care of ensuring that the module
661 * is single-threaded.
662 */
665 .common = {
666 .magic = MODULE_MAGIC_INIT,
667 .name = "json",
668 .onload = mod_load,
669 .unload = mod_unload,
671 .inst_size = sizeof(rlm_json_t),
672 .bootstrap = mod_bootstrap,
673 .instantiate = mod_instantiate
674 }
675};
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
#define fr_base16_encode(_out, _in)
Definition base16.h:54
#define fr_base64_encode(_out, _in, _add_padding)
Definition base64.h:71
#define RCSID(id)
Definition build.h:506
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:228
#define unlikely(_x)
Definition build.h:402
#define UNUSED
Definition build.h:336
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:657
#define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs)
conf_parser_t which populates a sub-struct using a CONF_SECTION
Definition cf_parse.h:309
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:594
Configuration AVP similar to a fr_pair_t.
Definition cf_priv.h:72
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:663
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:285
#define cf_canonicalize_error(_ci, _slen, _msg, _str)
Definition cf_util.h:363
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition dbuff.h:522
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
Definition dcursor.h:406
#define MEM(x)
Definition debug.h:46
static fr_slen_t in
Definition dict.h:882
Test enumeration values.
Definition dict_test.h:92
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
struct fr_jpath_node_s fr_jpath_node_t
Definition fuzzer_json.c:40
ssize_t fr_jpath_parse(void *ctx, fr_jpath_node_t **head, char const *in, size_t inlen)
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.
Definition rlm_json.c:199
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.
Definition rlm_json.c:177
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.
Definition rlm_json.c:255
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.
Definition rlm_json.c:212
talloc_free(hp)
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.
Definition json.c:1321
@ JSON_MODE_UNSET
Definition base.h:69
char * fr_jpath_asprint(TALLOC_CTX *ctx, fr_jpath_node_t const *head)
Print a node list to a string for debugging.
Definition jpath.c:411
struct fr_json_format_s fr_json_format_t
Definition base.h:243
@ JSON_BINARY_FORMAT_BASE64
Base64-encode octets values.
Definition base.h:58
@ JSON_BINARY_FORMAT_RAW
Current behaviour - raw bytes as JSON string.
Definition base.h:56
@ JSON_BINARY_FORMAT_BASE16
Base16-encode octets values.
Definition base.h:57
fr_slen_t fr_json_str_from_value(fr_sbuff_t *out, fr_value_box_t const *vb, bool include_quotes)
Print a value box as its equivalent JSON format without going via a struct json_object (in most cases...
Definition json.c:291
conf_parser_t const fr_json_format_config[]
Definition json.c:74
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.
Definition jpath.c:383
ssize_t fr_jpath_escape_func(UNUSED request_t *request, char *out, size_t outlen, char const *in, UNUSED void *arg)
Escapes special chars.
Definition jpath.c:106
void fr_json_version_print(void)
Print JSON-C version.
Definition json.c:475
fr_table_num_sorted_t const fr_json_format_table[]
Definition json.c:37
bool fr_json_format_verify(fr_json_format_t const *format, bool verbose)
Verify that the options in fr_json_format_t are valid.
Definition json.c:632
JSON document formatting options.
Definition base.h:231
#define RPERROR(fmt,...)
Definition log.h:314
#define REMARKER(_str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
Definition log.h:510
#define RPEDEBUG(fmt,...)
Definition log.h:388
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.
Definition map.c:1884
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.
Definition map_proc.c:124
void const * mpi
Map processor instance.
Definition map_proc.h:55
Temporary structure to hold arguments for map calls.
Definition map_proc.h:52
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT64
64 Bit unsigned integer.
@ FR_TYPE_VOID
User data.
@ FR_TYPE_OCTETS
Raw octets.
long int ssize_t
ssize_t fr_slen_t
module_instance_t const * mi
Instance of the module being instantiated.
Definition module_ctx.h:42
module_instance_t * mi
Instance of the module being instantiated.
Definition module_ctx.h:51
Temporary structure to hold arguments for instantiation calls.
Definition module_ctx.h:50
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)
Definition module_rlm.c:247
module_t common
Common fields presented by all modules.
Definition module_rlm.h:39
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
Definition pair.c:1352
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.
Definition pair.c:290
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition pair.c:46
int fr_pair_delete(fr_pair_list_t *list, fr_pair_t *vp)
Remove fr_pair_t from a list and free.
Definition pair.c:1833
#define fr_assert(_expr)
Definition rad_assert.h:37
#define REDEBUG(fmt,...)
static rs_t * conf
Definition radsniff.c:52
#define RETURN_UNLANG_RCODE(_rcode)
Definition rcode.h:61
#define RETURN_UNLANG_FAIL
Definition rcode.h:63
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:44
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition rcode.h:48
@ RLM_MODULE_UPDATED
OK (pairs modified).
Definition rcode.h:55
fr_dict_attr_t const * request_attr_request
Definition request.c:43
fr_json_format_t * format
Definition rlm_json.c:54
fr_jpath_node_t * jpath
First node in jpath expression.
Definition rlm_json.c:69
static xlat_arg_parser_t const json_escape_xlat_arg[]
Definition rlm_json.c:78
static int mod_load(void)
Definition rlm_json.c:637
json_object * root
Definition rlm_json.c:75
static xlat_action_t json_escape(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in, bool quote)
Definition rlm_json.c:83
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.
Definition rlm_json.c:373
static xlat_arg_parser_t const json_encode_xlat_arg[]
Definition rlm_json.c:243
static int mod_bootstrap(module_inst_ctx_t const *mctx)
Definition rlm_json.c:618
static void mod_unload(void)
Definition rlm_json.c:649
rlm_json_jpath_cache_t * next
Next jpath cache entry.
Definition rlm_json.c:70
static unlang_action_t mod_map_proc(unlang_result_t *p_result, map_ctx_t const *mpctx, 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.
Definition rlm_json.c:498
fr_jpath_node_t const * jpath
Definition rlm_json.c:74
static fr_sbuff_parse_rules_t const json_arg_parse_rules
Definition rlm_json.c:42
static xlat_arg_parser_t const json_jpath_validate_xlat_arg[]
Definition rlm_json.c:184
module_rlm_t rlm_json
Definition rlm_json.c:664
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.
Definition rlm_json.c:449
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition rlm_json.c:598
static conf_parser_t const module_config[]
Definition rlm_json.c:58
rlm_json module instance
Definition rlm_json.c:53
int fr_sbuff_reset_talloc(fr_sbuff_t *sbuff)
Reset a talloced buffer to its initial length, clearing any data stored.
Definition sbuff.c:467
bool fr_sbuff_next_if_char(fr_sbuff_t *sbuff, char c)
Return true if the current char matches, and if it does, advance.
Definition sbuff.c:2128
#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.
Definition sbuff.h:190
#define fr_sbuff_used(_sbuff_or_marker)
#define fr_sbuff_in_char(_sbuff,...)
#define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:351
void * data
Module's instance data.
Definition module.h:293
void * boot
Data allocated during the boostrap phase.
Definition module.h:296
conf_parser_t const * config
How to convert a CONF_SECTION to a module instance.
Definition module.h:206
#define tmpl_value_length(_tmpl)
Definition tmpl.h:938
#define tmpl_value(_tmpl)
Definition tmpl.h:937
#define tmpl_is_attr(vpt)
Definition tmpl.h:208
@ TMPL_TYPE_DATA
Value in native boxed format.
Definition tmpl.h:138
@ TMPL_TYPE_DATA_UNRESOLVED
Unparsed literal string.
Definition tmpl.h:179
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.
Definition tmpl_eval.c:685
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.
static fr_slen_t vpt
Definition tmpl.h:1269
#define tmpl_value_type(_tmpl)
Definition tmpl.h:939
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
Definition tmpl.h:801
#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.
Definition tmpl.h:1064
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:336
eap_aka_sim_process_conf_t * inst
fr_pair_t * vp
Value pair map.
Definition map.h:77
tmpl_t * lhs
Typically describes the attribute to add, modify or compare.
Definition map.h:78
tmpl_t * rhs
Typically describes a literal value or a src attribute to copy or compare.
Definition map.h:79
CONF_ITEM * ci
Config item that the map was created from.
Definition map.h:85
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition pair.h:69
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
Definition table.h:653
#define talloc_get_type_abort_const
Definition talloc.h:110
static size_t talloc_strlen(char const *s)
Returns the length of a talloc array containing a string.
Definition talloc.h:136
fr_type_t type
Type to cast argument to.
Definition xlat.h:155
@ XLAT_ARG_VARIADIC_EMPTY_SQUASH
Empty argument groups are removed.
Definition xlat.h:136
static fr_slen_t head
Definition xlat.h:420
unsigned int required
Argument must be present, and non-empty.
Definition xlat.h:146
unsigned int single
Argument must only contain a single box.
Definition xlat.h:148
#define XLAT_ARG_PARSER_TERMINATOR
Definition xlat.h:170
xlat_action_t
Definition xlat.h:37
@ XLAT_ACTION_FAIL
An xlat function failed.
Definition xlat.h:44
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition xlat.h:43
Definition for a single argument consumed by an xlat function.
Definition xlat.h:145
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.
Definition pair_inline.c:69
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.
Definition pair_inline.c:42
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:553
int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert one type of fr_value_box_t to another.
Definition value.c:3931
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.
Definition value.c:4692
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.
Definition value.c:4604
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.
Definition value.c:4537
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition value.c:4362
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.
Definition value.c:4823
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.
Definition value.c:4931
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.
Definition value.c:6585
@ FR_VALUE_BOX_LIST_FREE
Definition value.h:238
#define FR_VALUE_BOX_INITIALISER_NULL(_vb)
A static initialiser for stack/globally allocated boxes.
Definition value.h:511
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
Definition value.h:655
#define fr_value_box_list_foreach(_list_head, _iter)
Definition value.h:224
int format(printf, 5, 0))
static size_t char ** out
Definition value.h:1030
#define FR_VALUE_BOX_SAFE_FOR_ANY
Definition value.h:173
module_ctx_t const * mctx
Synthesised module calling ctx.
Definition xlat_ctx.h:52
An xlat calling ctx.
Definition xlat_ctx.h:49
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
Definition xlat_func.c:363
xlat_t * xlat_func_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function.
Definition xlat_func.c:216
void xlat_func_unregister(char const *name)
Unregister an xlat function.
Definition xlat_func.c:516