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: b294481f012c33d6276593f4df9eb2e575ca07da $
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: b294481f012c33d6276593f4df9eb2e575ca07da $")
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/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>
41
42#ifndef HAVE_JSON
43# error "rlm_json should not be built unless json-c is available"
44#endif
45
46static fr_sbuff_parse_rules_t const json_arg_parse_rules = {
47 .terminals = &FR_SBUFF_TERMS(
48 L("\t"),
49 L(" "),
50 L("!")
51 )
52};
53
54/** rlm_json module instance
55 *
56 */
57typedef struct {
60
61
62static conf_parser_t const module_config[] = {
64 .subcs_size = sizeof(fr_json_format_t), .subcs_type = "fr_json_format_t" },
65
67};
68
69/** Forms a linked list of jpath head node pointers (a list of jpaths)
70 */
73 fr_jpath_node_t *jpath; //!< First node in jpath expression.
74 rlm_json_jpath_cache_t *next; //!< Next jpath cache entry.
75};
76
77typedef struct {
79 json_object *root;
81
86
87static xlat_action_t json_escape(TALLOC_CTX *ctx, fr_dcursor_t *out,
88 UNUSED xlat_ctx_t const *xctx,
89 request_t *request, fr_value_box_list_t *in, bool quote)
90{
91 fr_value_box_t *vb_out;
92 fr_value_box_t *in_head = fr_value_box_list_head(in);
93 fr_sbuff_t *agg;
94
95 FR_SBUFF_TALLOC_THREAD_LOCAL(&agg, 1024, SIZE_MAX);
96
97 if (fr_value_box_list_num_elements(&in_head->vb_group) == 0) {
98 MEM(vb_out = fr_value_box_alloc_null(ctx));
99 fr_value_box_strdup(vb_out, vb_out, NULL, "null", false);
100 fr_dcursor_append(out, vb_out);
101
102 return XLAT_ACTION_DONE;
103 }
104
105 fr_value_box_list_foreach(&in_head->vb_group, vb_in) {
106 MEM(vb_out = fr_value_box_alloc_null(ctx));
107 if (fr_json_str_from_value(agg, vb_in, quote) < 0) {
108 RPERROR("Failed creating escaped JSON value");
109 return XLAT_ACTION_FAIL;
110 }
111 if (fr_value_box_bstrndup(vb_out, vb_out, NULL, fr_sbuff_start(agg), fr_sbuff_used(agg), vb_in->tainted) < 0) {
112 RPERROR("Failed assigning escaped JSON value to output box");
113 return XLAT_ACTION_FAIL;
114 }
116 fr_dcursor_append(out, vb_out);
117 }
118
119 return XLAT_ACTION_DONE;
120}
121/** Ensure contents are escaped correctly for a JSON document
122 *
123 * This allows values to be embedded inside JSON strings.
124 *
125 * @ingroup xlat_functions
126 *
127 */
129 xlat_ctx_t const *xctx,
130 request_t *request, fr_value_box_list_t *in)
131{
132 return json_escape(ctx, out, xctx, request, in, false);
133}
134
136 { .required = true, .concat = true, .type = FR_TYPE_STRING },
138};
139
140/** Ensure contents are quoted correctly for a JSON document
141 *
142 * This emits values with escaping, and appropriate quoting '"' depending on the
143 * type of values being produced. This lets boxed values be inserted directly
144 * as table values and array elements, without needing to determine if the
145 * expansion needs to be wrapped in quotes.
146 *
147 * @ingroup xlat_functions
148 *
149 */
151 xlat_ctx_t const *xctx,
152 request_t *request, fr_value_box_list_t *in)
153{
154 return json_escape(ctx, out, xctx, request, in, true);
155}
156
157/** Determine if a jpath expression is valid
158 *
159 * @ingroup xlat_functions
160 *
161 * Writes the output (in the format @verbatim<bytes parsed>[:error]@endverbatim).
162 */
164 UNUSED xlat_ctx_t const *xctx,
165 request_t *request, fr_value_box_list_t *in)
166{
167 fr_value_box_t *path = fr_value_box_list_head(in);
169 ssize_t slen;
170 char *jpath_str;
171 fr_value_box_t *vb;
172
173 MEM(vb = fr_value_box_alloc_null(ctx));
174
175 slen = fr_jpath_parse(request, &head, path->vb_strvalue, path->vb_length);
176 if (slen <= 0) {
177 fr_value_box_asprintf(ctx, vb, NULL, false, "%zu:%s", -(slen), fr_strerror());
179 fr_assert(head == NULL);
180 return XLAT_ACTION_DONE;
181 }
182 fr_assert(talloc_get_type_abort(head, fr_jpath_node_t));
183
184 jpath_str = fr_jpath_asprint(request, head);
185
186 fr_value_box_asprintf(ctx, vb, NULL, false, "%zu:%s", (size_t) slen, jpath_str);
189 talloc_free(jpath_str);
190
191 return XLAT_ACTION_DONE;
192}
193
195 { .single = true, .type = FR_TYPE_STRING, .required = true },
196 { .single = true, .type = FR_TYPE_STRING, .variadic = XLAT_ARG_VARIADIC_EMPTY_SQUASH },
198};
199
200/** Convert given attributes to a JSON document
201 *
202 * Usage is `%json.encode('attr', 'list[*]', '!negation)`
203 *
204 * @ingroup xlat_functions
205 */
207 xlat_ctx_t const *xctx,
208 request_t *request, fr_value_box_list_t *in)
209{
211 fr_json_format_t const *format = inst->format;
212
213 ssize_t slen;
214 tmpl_t *vpt = NULL;
215 fr_pair_list_t json_vps, vps;
216 bool negate;
217 char *json_str = NULL;
218 fr_value_box_t *vb;
219 fr_sbuff_t sbuff;
220
221 fr_pair_list_init(&json_vps);
222 fr_pair_list_init(&vps);
223
224 /*
225 * Iterate through the list of attribute templates in the xlat. For each
226 * one we either add it to the list of attributes for the JSON document
227 * or, if prefixed with '!', remove from the JSON list.
228 */
230 sbuff = FR_SBUFF_IN(ref->vb_strvalue, ref->vb_length);
231 fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX, NULL);
232 negate = false;
233
234 /* Check if we should be removing attributes */
235 if (fr_sbuff_next_if_char(&sbuff, '!')) negate = true;
236
237 /* Decode next attr template */
238 slen = tmpl_afrom_attr_substr(ctx, NULL, &vpt,
239 &sbuff,
241 &(tmpl_rules_t){
242 .attr = {
243 .list_def = request_attr_request,
244 .allow_wildcard = true,
245 .dict_def = request->local_dict,
246 }
247 });
248 if (slen <= 0) {
249 fr_sbuff_set(&sbuff, (size_t)(slen * -1));
250 REMARKER(fr_sbuff_start(&sbuff), fr_sbuff_used(&sbuff), "%s", fr_strerror());
251 error:
252 fr_pair_list_free(&json_vps);
254 return XLAT_ACTION_FAIL;
255 }
256
257 /*
258 * Get attributes from the template.
259 * Missing attribute isn't an error (so -1, not 0).
260 */
261 if (tmpl_copy_pairs(ctx, &vps, request, vpt) < -1) {
262 RPEDEBUG("Error copying attributes");
263 goto error;
264 }
265
266 if (negate) {
267 /* Remove all template attributes from JSON list */
268 for (fr_pair_t *vp = fr_pair_list_head(&vps);
269 vp;
270 vp = fr_pair_list_next(&vps, vp)) {
271
272 fr_pair_t *vpm = fr_pair_list_head(&json_vps);
273 while (vpm) {
274 if (vp->da == vpm->da) {
275 fr_pair_t *next = fr_pair_list_next(&json_vps, vpm);
276 fr_pair_delete(&json_vps, vpm);
277 vpm = next;
278 continue;
279 }
280 vpm = fr_pair_list_next(&json_vps, vpm);
281 }
282 }
283
284 fr_pair_list_free(&vps);
285 } else {
286 /* Add template VPs to JSON list */
287 fr_pair_list_append(&json_vps, &vps);
288 }
289
290 TALLOC_FREE(vpt);
291 }
292
293 /*
294 * Given the list of attributes we now have in json_vps,
295 * convert them into a JSON document and append it to the
296 * return cursor.
297 */
298 MEM(vb = fr_value_box_alloc_null(ctx));
299
300 json_str = fr_json_afrom_pair_list(vb, &json_vps, format);
301 if (!json_str) {
302 REDEBUG("Failed to generate JSON string");
303 goto error;
304 }
305 fr_value_box_bstrdup_buffer_shallow(NULL, vb, NULL, json_str, false);
306
308 fr_pair_list_free(&json_vps);
309
310 return XLAT_ACTION_DONE;
311}
312
313/** Pre-parse and validate literal jpath expressions for maps
314 *
315 * @param[in] cs #CONF_SECTION that defined the map instance.
316 * @param[in] mod_inst module instance (unused).
317 * @param[in] proc_inst the cache structure to fill.
318 * @param[in] src Where to get the JSON data from.
319 * @param[in] maps set of maps to translate to jpaths.
320 * @return
321 * - 0 on success.
322 * - -1 on failure.
323 */
324static int mod_map_proc_instantiate(CONF_SECTION *cs, UNUSED void const *mod_inst, void *proc_inst,
325 tmpl_t const *src, map_list_t const *maps)
326{
327 rlm_json_jpath_cache_t *cache_inst = proc_inst;
328 map_t const *map = NULL;
329 ssize_t slen;
330 rlm_json_jpath_cache_t *cache = cache_inst, **tail = &cache->next;
331
332 if (!src) {
333 cf_log_err(cs, "Missing JSON source");
334
335 return -1;
336 }
337
338 while ((map = map_list_next(maps, map))) {
339 CONF_PAIR *cp = cf_item_to_pair(map->ci);
340 char const *p;
341
342#ifndef HAVE_JSON_OBJECT_GET_INT64
343 if (tmpl_is_attr(map->lhs) && (tmpl_attr_tail_da(map->lhs)->type == FR_TYPE_UINT64)) {
344 cf_log_err(cp, "64bit integers are not supported by linked json-c. "
345 "Upgrade to json-c >= 0.10 to use this feature");
346 return -1;
347 }
348#endif
349
350 switch (map->rhs->type) {
352 p = map->rhs->name;
353 slen = fr_jpath_parse(cache, &cache->jpath, p, map->rhs->len);
354 if (slen <= 0) {
355 error:
356 cf_canonicalize_error(cp, slen, "Syntax error", fr_strerror());
357 return -1;
358 }
359 break;
360
361 case TMPL_TYPE_DATA:
362 if (tmpl_value_type(map->rhs) != FR_TYPE_STRING) {
363 cf_log_err(cp, "Right side of map must be a string");
364 return -1;
365 }
366 p = tmpl_value(map->rhs)->vb_strvalue;
367 slen = fr_jpath_parse(cache, &cache->jpath, p, tmpl_value_length(map->rhs));
368 if (slen <= 0) goto error;
369 break;
370
371 default:
372 continue;
373 }
374
375 /*
376 * Slightly weird... This is here because our first
377 * list member was pre-allocated and passed to the
378 * instantiation callback.
379 */
380 if (map_list_next(maps, map)) {
381 *tail = cache = talloc_zero(cache, rlm_json_jpath_cache_t);
382 tail = &cache->next;
383 }
384 }
385
386 return 0;
387}
388
389/** Converts a string value into a #fr_pair_t
390 *
391 * @param[in,out] ctx to allocate #fr_pair_t (s).
392 * @param[out] out where to write the resulting #fr_pair_t.
393 * @param[in] request The current request.
394 * @param[in] map to process.
395 * @param[in] uctx The json tree/jpath expression to evaluate.
396 * @return
397 * - 0 on success.
398 * - -1 on failure.
399 */
400static int _json_map_proc_get_value(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request,
401 map_t const *map, void *uctx)
402{
403 fr_pair_t *vp;
404 rlm_json_jpath_to_eval_t *to_eval = uctx;
406 fr_value_box_list_t head;
407 int ret;
408
410 fr_value_box_list_init(&head);
411
412 ret = fr_jpath_evaluate_leaf(request, &head, tmpl_attr_tail_da(map->lhs)->type, tmpl_attr_tail_da(map->lhs),
413 to_eval->root, to_eval->jpath);
414 if (ret < 0) {
415 RPEDEBUG("Failed evaluating jpath");
416 return -1;
417 }
418 if (ret == 0) return 0;
419 fr_assert(!fr_value_box_list_empty(&head));
420
421 for (value = fr_value_box_list_head(&head);
422 value;
423 fr_pair_append(out, vp), value = fr_value_box_list_next(&head, value)) {
425
426 if (fr_value_box_steal(vp, &vp->data, value) < 0) {
427 RPEDEBUG("Copying data to attribute failed");
430 return -1;
431 }
432 }
433
434 return 0;
435}
436
437/** Parses a JSON string, and executes jpath queries against it to map values to attributes
438 *
439 * @param p_result Result of applying map:
440 * - #RLM_MODULE_NOOP no rows were returned or columns matched.
441 * - #RLM_MODULE_UPDATED if one or more #fr_pair_t were added to the #request_t.
442 * - #RLM_MODULE_FAIL if a fault occurred.
443 * @param mpctx Call context for the map processor, containing the jpath cache.
444 * @param request The current request.
445 * @param json JSON string to parse.
446 * @param maps Head of the map list.
447 * @return UNLANG_ACTION_CALCULATE_RESULT
448 */
449static unlang_action_t mod_map_proc(unlang_result_t *p_result, map_ctx_t const *mpctx, request_t *request,
450 fr_value_box_list_t *json, map_list_t const *maps)
451{
453 struct json_tokener *tok;
454
455 rlm_json_jpath_cache_t const *cache = mpctx->mpi;
456 map_t const *map = NULL;
457
459
460 char const *json_str = NULL;
461 fr_value_box_t *json_head = fr_value_box_list_head(json);
462
463 if (!json_head) {
464 REDEBUG("JSON map input cannot be (null)");
466 }
467
469 json_head, json, FR_TYPE_STRING,
471 SIZE_MAX) < 0) {
472 REDEBUG("Failed concatenating input");
474 }
475 json_str = json_head->vb_strvalue;
476
477 if ((talloc_array_length(json_str) - 1) == 0) {
478 REDEBUG("JSON map input length must be > 0");
480 }
481
482 tok = json_tokener_new();
483 to_eval.root = json_tokener_parse_ex(tok, json_str, (int)(talloc_array_length(json_str) - 1));
484 if (!to_eval.root) {
485 REMARKER(json_str, tok->char_offset, "%s", json_tokener_error_desc(json_tokener_get_error(tok)));
486 rcode = RLM_MODULE_FAIL;
487 goto finish;
488 }
489
490 while ((map = map_list_next(maps, map))) {
491 switch (map->rhs->type) {
492 /*
493 * Cached types
494 */
496 case TMPL_TYPE_DATA:
497 to_eval.jpath = cache->jpath;
498
499 if (map_to_request(request, map, _json_map_proc_get_value, &to_eval) < 0) {
500 rcode = RLM_MODULE_FAIL;
501 goto finish;
502 }
503 cache = cache->next;
504 break;
505
506 /*
507 * Dynamic types
508 */
509 default:
510 {
511 ssize_t slen;
512 fr_jpath_node_t *node;
513 char *to_parse;
514
515 if (tmpl_aexpand(request, &to_parse, request, map->rhs, fr_jpath_escape_func, NULL) < 0) {
516 RPERROR("Failed getting jpath data");
517 rcode = RLM_MODULE_FAIL;
518 goto finish;
519 }
520 slen = fr_jpath_parse(request, &node, to_parse, talloc_array_length(to_parse) - 1);
521 if (slen <= 0) {
522 REMARKER(to_parse, -(slen), "%s", fr_strerror());
523 talloc_free(to_parse);
524 rcode = RLM_MODULE_FAIL;
525 goto finish;
526 }
527 to_eval.jpath = node;
528
529 if (map_to_request(request, map, _json_map_proc_get_value, &to_eval) < 0) {
530 talloc_free(node);
531 talloc_free(to_parse);
532 rcode = RLM_MODULE_FAIL;
533 goto finish;
534 }
535 talloc_free(node);
536 }
537 break;
538 }
539 }
540
541
542finish:
543 json_object_put(to_eval.root);
544 json_tokener_free(tok);
545
546 RETURN_UNLANG_RCODE(rcode);
547}
548
549static int mod_instantiate(module_inst_ctx_t const *mctx)
550{
551 rlm_json_t const *inst = talloc_get_type_abort(mctx->mi->data, rlm_json_t);
552 CONF_SECTION *conf = mctx->mi->conf;
553 fr_json_format_t *format = inst->format;
554
555 /*
556 * Check the output format type and warn on unused
557 * format options
558 */
560 if (format->output_mode == JSON_MODE_UNSET) {
561 cf_log_err(conf, "output_mode value \"%s\" is invalid", format->output_mode_str);
562 return -1;
563 }
565
566 return 0;
567}
568
569static int mod_bootstrap(module_inst_ctx_t const *mctx)
570{
571 rlm_json_t const *inst = talloc_get_type_abort(mctx->mi->data, rlm_json_t);
572 xlat_t *xlat;
573
574 xlat = module_rlm_xlat_register(mctx->mi->boot, mctx, "encode", json_encode_xlat, FR_TYPE_STRING);
576
577 if (map_proc_register(mctx->mi->boot, inst, "json", mod_map_proc,
579 return 0;
580}
581
582static int mod_load(void)
583{
584 xlat_t *xlat;
585
587
588 if (unlikely(!(xlat = xlat_func_register(NULL, "json.escape", json_escape_xlat, FR_TYPE_STRING)))) return -1;
590 if (unlikely(!(xlat = xlat_func_register(NULL, "json.quote", json_quote_xlat, FR_TYPE_STRING)))) return -1;
592 if (unlikely(!(xlat = xlat_func_register(NULL, "json.jpath_validate", json_jpath_validate_xlat, FR_TYPE_STRING)))) return -1;
594
595 return 0;
596}
597
598static void mod_unload(void)
599{
600 xlat_func_unregister("json.escape");
601 xlat_func_unregister("json.quote");
602 xlat_func_unregister("json.jpath_validate");
603}
604
605/*
606 * The module name should be the only globally exported symbol.
607 * That is, everything else should be 'static'.
608 *
609 * If the module needs to temporarily modify it's instantiation
610 * data, the type should be changed to MODULE_TYPE_THREAD_UNSAFE.
611 * The server will then take care of ensuring that the module
612 * is single-threaded.
613 */
616 .common = {
617 .magic = MODULE_MAGIC_INIT,
618 .name = "json",
619 .onload = mod_load,
620 .unload = mod_unload,
622 .inst_size = sizeof(rlm_json_t),
623 .bootstrap = mod_bootstrap,
624 .instantiate = mod_instantiate
625 }
626};
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
#define RCSID(id)
Definition build.h:485
#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:70
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:286
#define cf_canonicalize_error(_ci, _slen, _msg, _str)
Definition cf_util.h:364
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:861
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:150
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:128
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:206
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:163
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:1238
@ JSON_MODE_UNSET
Definition base.h:58
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:231
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...
Definition json.c:279
conf_parser_t const fr_json_format_config[]
Definition json.c:63
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:458
fr_table_num_sorted_t const fr_json_format_table[]
Definition json.c:36
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:558
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:219
#define RPERROR(fmt,...)
Definition log.h:302
#define REMARKER(_str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
Definition log.h:498
#define RPEDEBUG(fmt,...)
Definition log.h:376
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:1872
talloc_free(reap)
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.
long int ssize_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:1345
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:287
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:1824
#define fr_assert(_expr)
Definition rad_assert.h:38
#define REDEBUG(fmt,...)
Definition radclient.h:52
static rs_t * conf
Definition radsniff.c:53
#define RETURN_UNLANG_RCODE(_rcode)
Definition rcode.h:57
#define RETURN_UNLANG_FAIL
Definition rcode.h:59
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:40
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition rcode.h:44
@ RLM_MODULE_UPDATED
OK (pairs modified).
Definition rcode.h:51
fr_dict_attr_t const * request_attr_request
Definition request.c:43
fr_json_format_t * format
Definition rlm_json.c:58
fr_jpath_node_t * jpath
First node in jpath expression.
Definition rlm_json.c:73
static xlat_arg_parser_t const json_escape_xlat_arg[]
Definition rlm_json.c:82
static int mod_load(void)
Definition rlm_json.c:582
json_object * root
Definition rlm_json.c:79
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:324
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)
Definition rlm_json.c:87
static xlat_arg_parser_t const json_encode_xlat_arg[]
Definition rlm_json.c:194
static int mod_bootstrap(module_inst_ctx_t const *mctx)
Definition rlm_json.c:569
static void mod_unload(void)
Definition rlm_json.c:598
rlm_json_jpath_cache_t * next
Next jpath cache entry.
Definition rlm_json.c:74
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:449
fr_jpath_node_t const * jpath
Definition rlm_json.c:78
static fr_sbuff_parse_rules_t const json_arg_parse_rules
Definition rlm_json.c:46
static xlat_arg_parser_t const json_jpath_validate_xlat_arg[]
Definition rlm_json.c:135
module_rlm_t rlm_json
Definition rlm_json.c:615
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:400
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition rlm_json.c:549
static conf_parser_t const module_config[]
Definition rlm_json.c:62
rlm_json module instance
Definition rlm_json.c:57
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:2116
#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:192
#define fr_sbuff_used(_sbuff_or_marker)
#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:681
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:1062
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:332
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:287
fr_type_t type
Type to cast argument to.
Definition xlat.h:155
uint8_t single
Argument must only contain a single box.
Definition xlat.h:148
@ XLAT_ARG_VARIADIC_EMPTY_SQUASH
Empty argument groups are removed.
Definition xlat.h:136
static fr_slen_t head
Definition xlat.h:420
uint8_t required
Argument must be present, and non-empty.
Definition xlat.h:146
#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_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:4455
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:4368
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:4301
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:4589
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:4694
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:6274
@ FR_VALUE_BOX_LIST_FREE
Definition value.h:239
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
Definition value.h:654
#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:1023
#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