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: 607894f7a293f766368bc39f9d54177b07635ba9 $
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: 607894f7a293f766368bc39f9d54177b07635ba9 $")
30
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/base64.h>
36#include <freeradius-devel/util/debug.h>
37#include <freeradius-devel/util/sbuff.h>
38#include <freeradius-devel/util/types.h>
39#include <freeradius-devel/util/value.h>
40#include <freeradius-devel/unlang/xlat_func.h>
41#include <freeradius-devel/json/base.h>
42
43#ifndef HAVE_JSON
44# error "rlm_json should not be built unless json-c is available"
45#endif
46
47static fr_sbuff_parse_rules_t const json_arg_parse_rules = {
48 .terminals = &FR_SBUFF_TERMS(
49 L("\t"),
50 L(" "),
51 L("!")
52 )
53};
54
55/** rlm_json module instance
56 *
57 */
58typedef struct {
61
62
63static conf_parser_t const module_config[] = {
65 .subcs_size = sizeof(fr_json_format_t), .subcs_type = "fr_json_format_t" },
66
68};
69
70/** Forms a linked list of jpath head node pointers (a list of jpaths)
71 */
74 fr_jpath_node_t *jpath; //!< First node in jpath expression.
75 rlm_json_jpath_cache_t *next; //!< Next jpath cache entry.
76};
77
78typedef struct {
80 json_object *root;
82
87
88static xlat_action_t json_escape(TALLOC_CTX *ctx, fr_dcursor_t *out,
89 xlat_ctx_t const *xctx,
90 request_t *request, fr_value_box_list_t *in, bool quote)
91{
93 fr_json_format_t const *format = inst->format;
94 fr_value_box_t *vb_out;
95 fr_value_box_t *in_head = fr_value_box_list_head(in);
96 fr_sbuff_t *agg;
97
98 FR_SBUFF_TALLOC_THREAD_LOCAL(&agg, 1024, SIZE_MAX);
99
100 if (fr_value_box_list_num_elements(&in_head->vb_group) == 0) {
101 MEM(vb_out = fr_value_box_alloc_null(ctx));
102 fr_value_box_strdup(vb_out, vb_out, NULL, "null", false);
103 fr_dcursor_append(out, vb_out);
104
105 return XLAT_ACTION_DONE;
106 }
107
108 fr_value_box_list_foreach(&in_head->vb_group, vb_in) {
109 fr_value_box_t *vb_to_encode = vb_in;
111 fr_slen_t slen;
112
113 if (format) {
114 /*
115 * Encode octets as base16 or base64 when requested.
116 */
117 if ((vb_in->type == FR_TYPE_OCTETS) &&
118 (format->value.binary_format != JSON_BINARY_FORMAT_RAW)) {
119 MEM(vb_out = fr_value_box_alloc_null(ctx));
120 if (quote) fr_sbuff_in_char(agg, '"');
121 switch (format->value.binary_format) {
122 /*
123 * Hex encode octets values when requested.
124 */
126 fr_base16_encode(agg, &FR_DBUFF_TMP(vb_in->vb_octets, vb_in->vb_length));
127 break;
128
129 /*
130 * Base64-encode octets values when requested.
131 */
133 fr_base64_encode(agg, &FR_DBUFF_TMP(vb_in->vb_octets, vb_in->vb_length), true);
134 break;
135
136 default:
137 fr_assert(0); /* ENUM updated and no encode() function */
138 break;
139 }
140 if (quote) fr_sbuff_in_char(agg, '"');
141 goto assign;
142 }
143
144 /*
145 * Cast to string when always_string is set.
146 */
147 if (format->value.always_string && (vb_in->type != FR_TYPE_STRING)) {
148 if (unlikely(fr_value_box_cast(ctx, &vb_str, FR_TYPE_STRING, NULL, vb_to_encode) < 0)) {
149 RPERROR("Failed casting value to string");
150 return XLAT_ACTION_FAIL;
151 }
152 vb_to_encode = &vb_str;
153 }
154 }
155
156 MEM(vb_out = fr_value_box_alloc_null(ctx));
157 slen = fr_json_str_from_value(agg, vb_to_encode, quote);
158 fr_value_box_clear(&vb_str);
159 if (slen < 0) {
160 RPERROR("Failed creating escaped JSON value");
161 return XLAT_ACTION_FAIL;
162 }
163
164 assign:
165 if (fr_value_box_bstrndup(vb_out, vb_out, NULL, fr_sbuff_start(agg), fr_sbuff_used(agg), vb_in->tainted) < 0) {
166 RPERROR("Failed assigning escaped JSON value to output box");
167 return XLAT_ACTION_FAIL;
168 }
170 fr_dcursor_append(out, vb_out);
171 }
172
173 return XLAT_ACTION_DONE;
174}
175/** Ensure contents are escaped correctly for a JSON document
176 *
177 * This allows values to be embedded inside JSON strings.
178 *
179 * @ingroup xlat_functions
180 *
181 */
183 xlat_ctx_t const *xctx,
184 request_t *request, fr_value_box_list_t *in)
185{
186 return json_escape(ctx, out, xctx, request, in, false);
187}
188
190 { .required = true, .concat = true, .type = FR_TYPE_STRING },
192};
193
194/** Ensure contents are quoted correctly for a JSON document
195 *
196 * This emits values with escaping, and appropriate quoting '"' depending on the
197 * type of values being produced. This lets boxed values be inserted directly
198 * as table values and array elements, without needing to determine if the
199 * expansion needs to be wrapped in quotes.
200 *
201 * @ingroup xlat_functions
202 *
203 */
205 xlat_ctx_t const *xctx,
206 request_t *request, fr_value_box_list_t *in)
207{
208 return json_escape(ctx, out, xctx, request, in, true);
209}
210
211/** Determine if a jpath expression is valid
212 *
213 * @ingroup xlat_functions
214 *
215 * Writes the output (in the format @verbatim<bytes parsed>[:error]@endverbatim).
216 */
218 UNUSED xlat_ctx_t const *xctx,
219 request_t *request, fr_value_box_list_t *in)
220{
221 fr_value_box_t *path = fr_value_box_list_head(in);
223 ssize_t slen;
224 char *jpath_str;
225 fr_value_box_t *vb;
226
227 MEM(vb = fr_value_box_alloc_null(ctx));
228
229 slen = fr_jpath_parse(request, &head, path->vb_strvalue, path->vb_length);
230 if (slen <= 0) {
231 fr_value_box_asprintf(ctx, vb, NULL, false, "%zu:%s", -(slen), fr_strerror());
233 fr_assert(head == NULL);
234 return XLAT_ACTION_DONE;
235 }
236 fr_assert(talloc_get_type_abort(head, fr_jpath_node_t));
237
238 jpath_str = fr_jpath_asprint(request, head);
239
240 fr_value_box_asprintf(ctx, vb, NULL, false, "%zu:%s", (size_t) slen, jpath_str);
243 talloc_free(jpath_str);
244
245 return XLAT_ACTION_DONE;
246}
247
249 { .single = true, .type = FR_TYPE_STRING, .required = true },
250 { .single = true, .type = FR_TYPE_STRING, .variadic = XLAT_ARG_VARIADIC_EMPTY_SQUASH },
252};
253
254/** Convert given attributes to a JSON document
255 *
256 * Usage is `%json.encode('attr', 'list[*]', '!negation)`
257 *
258 * @ingroup xlat_functions
259 */
261 xlat_ctx_t const *xctx,
262 request_t *request, fr_value_box_list_t *in)
263{
265 fr_json_format_t const *format = inst->format;
266
267 ssize_t slen;
268 tmpl_t *vpt = NULL;
269 fr_pair_list_t json_vps, vps;
270 bool negate;
271 char *json_str = NULL;
272 fr_value_box_t *vb;
273 fr_sbuff_t sbuff;
274
275 fr_pair_list_init(&json_vps);
276 fr_pair_list_init(&vps);
277
278 /*
279 * Iterate through the list of attribute templates in the xlat. For each
280 * one we either add it to the list of attributes for the JSON document
281 * or, if prefixed with '!', remove from the JSON list.
282 */
284 sbuff = FR_SBUFF_IN(ref->vb_strvalue, ref->vb_length);
285 fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX, NULL);
286 negate = false;
287
288 /* Check if we should be removing attributes */
289 if (fr_sbuff_next_if_char(&sbuff, '!')) negate = true;
290
291 /* Decode next attr template */
292 slen = tmpl_afrom_attr_substr(ctx, NULL, &vpt,
293 &sbuff,
295 &(tmpl_rules_t){
296 .attr = {
297 .list_def = request_attr_request,
298 .allow_wildcard = true,
299 .dict_def = request->local_dict,
300 }
301 });
302 if (slen <= 0) {
303 fr_sbuff_set(&sbuff, (size_t)(slen * -1));
304 REMARKER(fr_sbuff_start(&sbuff), fr_sbuff_used(&sbuff), "%s", fr_strerror());
305 error:
306 fr_pair_list_free(&json_vps);
308 return XLAT_ACTION_FAIL;
309 }
310
311 /*
312 * Get attributes from the template.
313 * Missing attribute isn't an error (so -1, not 0).
314 */
315 if (tmpl_copy_pairs(ctx, &vps, request, vpt) < -1) {
316 RPEDEBUG("Error copying attributes");
317 goto error;
318 }
319
320 if (negate) {
321 /* Remove all template attributes from JSON list */
322 for (fr_pair_t *vp = fr_pair_list_head(&vps);
323 vp;
324 vp = fr_pair_list_next(&vps, vp)) {
325
326 fr_pair_t *vpm = fr_pair_list_head(&json_vps);
327 while (vpm) {
328 if (vp->da == vpm->da) {
329 fr_pair_t *next = fr_pair_list_next(&json_vps, vpm);
330 fr_pair_delete(&json_vps, vpm);
331 vpm = next;
332 continue;
333 }
334 vpm = fr_pair_list_next(&json_vps, vpm);
335 }
336 }
337
338 fr_pair_list_free(&vps);
339 } else {
340 /* Add template VPs to JSON list */
341 fr_pair_list_append(&json_vps, &vps);
342 }
343
344 TALLOC_FREE(vpt);
345 }
346
347 /*
348 * Given the list of attributes we now have in json_vps,
349 * convert them into a JSON document and append it to the
350 * return cursor.
351 */
352 MEM(vb = fr_value_box_alloc_null(ctx));
353
354 json_str = fr_json_afrom_pair_list(vb, &json_vps, format);
355 if (!json_str) {
356 REDEBUG("Failed to generate JSON string");
357 goto error;
358 }
359 fr_value_box_bstrdup_buffer_shallow(NULL, vb, NULL, json_str, false);
360
362 fr_pair_list_free(&json_vps);
363
364 return XLAT_ACTION_DONE;
365}
366
367/** Pre-parse and validate literal jpath expressions for maps
368 *
369 * @param[in] cs #CONF_SECTION that defined the map instance.
370 * @param[in] mod_inst module instance (unused).
371 * @param[in] proc_inst the cache structure to fill.
372 * @param[in] src Where to get the JSON data from.
373 * @param[in] maps set of maps to translate to jpaths.
374 * @return
375 * - 0 on success.
376 * - -1 on failure.
377 */
378static int mod_map_proc_instantiate(CONF_SECTION *cs, UNUSED void const *mod_inst, void *proc_inst,
379 tmpl_t const *src, map_list_t const *maps)
380{
381 rlm_json_jpath_cache_t *cache_inst = proc_inst;
382 map_t const *map = NULL;
383 ssize_t slen;
384 rlm_json_jpath_cache_t *cache = cache_inst, **tail = &cache->next;
385
386 if (!src) {
387 cf_log_err(cs, "Missing JSON source");
388
389 return -1;
390 }
391
392 while ((map = map_list_next(maps, map))) {
393 CONF_PAIR *cp = cf_item_to_pair(map->ci);
394 char const *p;
395
396#ifndef HAVE_JSON_OBJECT_GET_INT64
397 if (tmpl_is_attr(map->lhs) && (tmpl_attr_tail_da(map->lhs)->type == FR_TYPE_UINT64)) {
398 cf_log_err(cp, "64bit integers are not supported by linked json-c. "
399 "Upgrade to json-c >= 0.10 to use this feature");
400 return -1;
401 }
402#endif
403
404 switch (map->rhs->type) {
406 p = map->rhs->name;
407 slen = fr_jpath_parse(cache, &cache->jpath, p, map->rhs->len);
408 if (slen <= 0) {
409 error:
410 cf_canonicalize_error(cp, slen, "Syntax error", fr_strerror());
411 return -1;
412 }
413 break;
414
415 case TMPL_TYPE_DATA:
416 if (tmpl_value_type(map->rhs) != FR_TYPE_STRING) {
417 cf_log_err(cp, "Right side of map must be a string");
418 return -1;
419 }
420 p = tmpl_value(map->rhs)->vb_strvalue;
421 slen = fr_jpath_parse(cache, &cache->jpath, p, tmpl_value_length(map->rhs));
422 if (slen <= 0) goto error;
423 break;
424
425 default:
426 continue;
427 }
428
429 /*
430 * Slightly weird... This is here because our first
431 * list member was pre-allocated and passed to the
432 * instantiation callback.
433 */
434 if (map_list_next(maps, map)) {
435 *tail = cache = talloc_zero(cache, rlm_json_jpath_cache_t);
436 tail = &cache->next;
437 }
438 }
439
440 return 0;
441}
442
443/** Converts a string value into a #fr_pair_t
444 *
445 * @param[in,out] ctx to allocate #fr_pair_t (s).
446 * @param[out] out where to write the resulting #fr_pair_t.
447 * @param[in] request The current request.
448 * @param[in] map to process.
449 * @param[in] uctx The json tree/jpath expression to evaluate.
450 * @return
451 * - 0 on success.
452 * - -1 on failure.
453 */
454static int _json_map_proc_get_value(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request,
455 map_t const *map, void *uctx)
456{
457 fr_pair_t *vp;
458 rlm_json_jpath_to_eval_t *to_eval = uctx;
460 fr_value_box_list_t head;
461 int ret;
462
464 fr_value_box_list_init(&head);
465
466 ret = fr_jpath_evaluate_leaf(request, &head, tmpl_attr_tail_da(map->lhs)->type, tmpl_attr_tail_da(map->lhs),
467 to_eval->root, to_eval->jpath);
468 if (ret < 0) {
469 RPEDEBUG("Failed evaluating jpath");
470 return -1;
471 }
472 if (ret == 0) return 0;
473 fr_assert(!fr_value_box_list_empty(&head));
474
475 for (value = fr_value_box_list_head(&head);
476 value;
477 fr_pair_append(out, vp), value = fr_value_box_list_next(&head, value)) {
479
480 if (fr_value_box_steal(vp, &vp->data, value) < 0) {
481 RPEDEBUG("Copying data to attribute failed");
484 return -1;
485 }
486 }
487
488 return 0;
489}
490
491/** Parses a JSON string, and executes jpath queries against it to map values to attributes
492 *
493 * @param p_result Result of applying map:
494 * - #RLM_MODULE_NOOP no rows were returned or columns matched.
495 * - #RLM_MODULE_UPDATED if one or more #fr_pair_t were added to the #request_t.
496 * - #RLM_MODULE_FAIL if a fault occurred.
497 * @param mpctx Call context for the map processor, containing the jpath cache.
498 * @param request The current request.
499 * @param json JSON string to parse.
500 * @param maps Head of the map list.
501 * @return UNLANG_ACTION_CALCULATE_RESULT
502 */
503static unlang_action_t mod_map_proc(unlang_result_t *p_result, map_ctx_t const *mpctx, request_t *request,
504 fr_value_box_list_t *json, map_list_t const *maps)
505{
507 struct json_tokener *tok;
508
509 rlm_json_jpath_cache_t const *cache = mpctx->mpi;
510 map_t const *map = NULL;
511
513
514 char const *json_str = NULL;
515 fr_value_box_t *json_head = fr_value_box_list_head(json);
516
517 if (!json_head) {
518 REDEBUG("JSON map input cannot be (null)");
520 }
521
523 json_head, json, FR_TYPE_STRING,
525 SIZE_MAX) < 0) {
526 REDEBUG("Failed concatenating input");
528 }
529 json_str = json_head->vb_strvalue;
530
531 if ((talloc_array_length(json_str) - 1) == 0) {
532 REDEBUG("JSON map input length must be > 0");
534 }
535
536 tok = json_tokener_new();
537 to_eval.root = json_tokener_parse_ex(tok, json_str, (int)(talloc_array_length(json_str) - 1));
538 if (!to_eval.root) {
539 REMARKER(json_str, tok->char_offset, "%s", json_tokener_error_desc(json_tokener_get_error(tok)));
540 rcode = RLM_MODULE_FAIL;
541 goto finish;
542 }
543
544 while ((map = map_list_next(maps, map))) {
545 switch (map->rhs->type) {
546 /*
547 * Cached types
548 */
550 case TMPL_TYPE_DATA:
551 to_eval.jpath = cache->jpath;
552
553 if (map_to_request(request, map, _json_map_proc_get_value, &to_eval) < 0) {
554 rcode = RLM_MODULE_FAIL;
555 goto finish;
556 }
557 cache = cache->next;
558 break;
559
560 /*
561 * Dynamic types
562 */
563 default:
564 {
565 ssize_t slen;
566 fr_jpath_node_t *node;
567 char *to_parse;
568
569 if (tmpl_aexpand(request, &to_parse, request, map->rhs, fr_jpath_escape_func, NULL) < 0) {
570 RPERROR("Failed getting jpath data");
571 rcode = RLM_MODULE_FAIL;
572 goto finish;
573 }
574 slen = fr_jpath_parse(request, &node, to_parse, talloc_array_length(to_parse) - 1);
575 if (slen <= 0) {
576 REMARKER(to_parse, -(slen), "%s", fr_strerror());
577 talloc_free(to_parse);
578 rcode = RLM_MODULE_FAIL;
579 goto finish;
580 }
581 to_eval.jpath = node;
582
583 if (map_to_request(request, map, _json_map_proc_get_value, &to_eval) < 0) {
584 talloc_free(node);
585 talloc_free(to_parse);
586 rcode = RLM_MODULE_FAIL;
587 goto finish;
588 }
589 talloc_free(node);
590 }
591 break;
592 }
593 }
594
595
596finish:
597 json_object_put(to_eval.root);
598 json_tokener_free(tok);
599
600 RETURN_UNLANG_RCODE(rcode);
601}
602
603static int mod_instantiate(module_inst_ctx_t const *mctx)
604{
605 rlm_json_t const *inst = talloc_get_type_abort(mctx->mi->data, rlm_json_t);
606 CONF_SECTION *conf = mctx->mi->conf;
607 fr_json_format_t *format = inst->format;
608
609 /*
610 * Check the output format type and warn on unused
611 * format options
612 */
614 if (format->output_mode == JSON_MODE_UNSET) {
615 cf_log_err(conf, "output_mode value \"%s\" is invalid", format->output_mode_str);
616 return -1;
617 }
619
620 return 0;
621}
622
623static int mod_bootstrap(module_inst_ctx_t const *mctx)
624{
625 rlm_json_t const *inst = talloc_get_type_abort(mctx->mi->data, rlm_json_t);
626 xlat_t *xlat;
627
628 xlat = module_rlm_xlat_register(mctx->mi->boot, mctx, "encode", json_encode_xlat, FR_TYPE_STRING);
630
631 xlat = module_rlm_xlat_register(mctx->mi->boot, mctx, "escape", json_escape_xlat, FR_TYPE_STRING);
633
634 xlat = module_rlm_xlat_register(mctx->mi->boot, mctx, "quote", json_quote_xlat, FR_TYPE_STRING);
636
637 if (map_proc_register(mctx->mi->boot, inst, "json", mod_map_proc,
639 return 0;
640}
641
642static int mod_load(void)
643{
644 xlat_t *xlat;
645
647
648 if (unlikely(!(xlat = xlat_func_register(NULL, "json.jpath_validate", json_jpath_validate_xlat, FR_TYPE_STRING)))) return -1;
650
651 return 0;
652}
653
654static void mod_unload(void)
655{
656 xlat_func_unregister("json.jpath_validate");
657}
658
659/*
660 * The module name should be the only globally exported symbol.
661 * That is, everything else should be 'static'.
662 *
663 * If the module needs to temporarily modify it's instantiation
664 * data, the type should be changed to MODULE_TYPE_THREAD_UNSAFE.
665 * The server will then take care of ensuring that the module
666 * is single-threaded.
667 */
670 .common = {
671 .magic = MODULE_MAGIC_INIT,
672 .name = "json",
673 .onload = mod_load,
674 .unload = mod_unload,
676 .inst_size = sizeof(rlm_json_t),
677 .bootstrap = mod_bootstrap,
678 .instantiate = mod_instantiate
679 }
680};
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:57
#define fr_base64_encode(_out, _in, _add_padding)
Definition base64.h:74
#define RCSID(id)
Definition build.h:487
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:209
#define unlikely(_x)
Definition build.h:383
#define UNUSED
Definition build.h:317
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:660
#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:312
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:597
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:288
#define cf_canonicalize_error(_ci, _slen, _msg, _str)
Definition cf_util.h:366
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition dbuff.h:524
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
Definition dcursor.h:408
#define MEM(x)
Definition debug.h:36
static fr_slen_t in
Definition dict.h:884
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
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:204
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:182
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:260
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:217
talloc_free(hp)
Node in a jpath selector sequence.
Definition jpath.c:87
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:1322
@ 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:292
conf_parser_t const fr_json_format_config[]
Definition json.c:75
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:476
fr_table_num_sorted_t const fr_json_format_table[]
Definition json.c:38
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:633
ssize_t fr_jpath_parse(TALLOC_CTX *ctx, fr_jpath_node_t **head, char const *in, size_t inlen)
Parse a jpath string.
Definition jpath.c:813
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:1876
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:125
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:1349
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:1830
#define fr_assert(_expr)
Definition rad_assert.h:38
#define REDEBUG(fmt,...)
static rs_t * conf
Definition radsniff.c:53
#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:59
fr_jpath_node_t * jpath
First node in jpath expression.
Definition rlm_json.c:74
static xlat_arg_parser_t const json_escape_xlat_arg[]
Definition rlm_json.c:83
static int mod_load(void)
Definition rlm_json.c:642
json_object * root
Definition rlm_json.c:80
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:88
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:378
static xlat_arg_parser_t const json_encode_xlat_arg[]
Definition rlm_json.c:248
static int mod_bootstrap(module_inst_ctx_t const *mctx)
Definition rlm_json.c:623
static void mod_unload(void)
Definition rlm_json.c:654
rlm_json_jpath_cache_t * next
Next jpath cache entry.
Definition rlm_json.c:75
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:503
fr_jpath_node_t const * jpath
Definition rlm_json.c:79
static fr_sbuff_parse_rules_t const json_arg_parse_rules
Definition rlm_json.c:47
static xlat_arg_parser_t const json_jpath_validate_xlat_arg[]
Definition rlm_json.c:189
module_rlm_t rlm_json
Definition rlm_json.c:669
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:454
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition rlm_json.c:603
static conf_parser_t const module_config[]
Definition rlm_json.c:63
rlm_json module instance
Definition rlm_json.c:58
int fr_sbuff_reset_talloc(fr_sbuff_t *sbuff)
Reset a talloced buffer to its initial length, clearing any data stored.
Definition sbuff.c:459
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:2121
#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:193
#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:349
void * data
Module's instance data.
Definition module.h:291
void * boot
Data allocated during the boostrap phase.
Definition module.h:294
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:245
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 consumend 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:3961
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:4722
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:4634
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:4567
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition value.c:4392
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:4853
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:4961
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:6612
@ 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:1024
#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