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: 8cc447c7d890b2870d66730ab44ea78371ef73f7 $
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: 8cc447c7d890b2870d66730ab44ea78371ef73f7 $")
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 { .required = true, .concat = true, .type = FR_TYPE_STRING },
197};
198
199/** Convert given attributes to a JSON document
200 *
201 * Usage is `%json.encode(attr tmpl list)`
202 *
203 * @ingroup xlat_functions
204 */
206 xlat_ctx_t const *xctx,
207 request_t *request, fr_value_box_list_t *in)
208{
210 fr_json_format_t const *format = inst->format;
211
212 ssize_t slen;
213 tmpl_t *vpt = NULL;
214 fr_pair_list_t json_vps, vps;
215 bool negate;
216 char *json_str = NULL;
217 fr_value_box_t *vb;
218 fr_sbuff_t sbuff;
219 fr_value_box_t *in_head = fr_value_box_list_head(in);
220
221 fr_pair_list_init(&json_vps);
222 fr_pair_list_init(&vps);
223
224 sbuff = FR_SBUFF_IN(in_head->vb_strvalue, in_head->vb_length);
225 fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX, NULL);
226
227 /*
228 * Iterate through the list of attribute templates in the xlat. For each
229 * one we either add it to the list of attributes for the JSON document
230 * or, if prefixed with '!', remove from the JSON list.
231 */
232 while (fr_sbuff_extend(&sbuff)) {
233 negate = false;
234
235 /* Check if we should be removing attributes */
236 if (fr_sbuff_next_if_char(&sbuff, '!')) negate = true;
237
238 /* Decode next attr template */
239 slen = tmpl_afrom_attr_substr(ctx, NULL, &vpt,
240 &sbuff,
242 &(tmpl_rules_t){
243 .attr = {
244 .list_def = request_attr_request,
245 .allow_wildcard = true,
246 .dict_def = request->dict
247 }
248 });
249 if (slen <= 0) {
250 fr_sbuff_set(&sbuff, (size_t)(slen * -1));
251 REMARKER(fr_sbuff_start(&sbuff), fr_sbuff_used(&sbuff), "%s", fr_strerror());
252 error:
253 fr_pair_list_free(&json_vps);
255 return XLAT_ACTION_FAIL;
256 }
257
258 /*
259 * Get attributes from the template.
260 * Missing attribute isn't an error (so -1, not 0).
261 */
262 if (tmpl_copy_pairs(ctx, &vps, request, vpt) < -1) {
263 RPEDEBUG("Error copying attributes");
264 goto error;
265 }
266
267 if (negate) {
268 /* Remove all template attributes from JSON list */
269 for (fr_pair_t *vp = fr_pair_list_head(&vps);
270 vp;
271 vp = fr_pair_list_next(&vps, vp)) {
272
273 fr_pair_t *vpm = fr_pair_list_head(&json_vps);
274 while (vpm) {
275 if (vp->da == vpm->da) {
276 fr_pair_t *next = fr_pair_list_next(&json_vps, vpm);
277 fr_pair_delete(&json_vps, vpm);
278 vpm = next;
279 continue;
280 }
281 vpm = fr_pair_list_next(&json_vps, vpm);
282 }
283 }
284
285 fr_pair_list_free(&vps);
286 } else {
287 /* Add template VPs to JSON list */
288 fr_pair_list_append(&json_vps, &vps);
289 }
290
291 TALLOC_FREE(vpt);
292
293 /* Jump forward to next attr */
294 fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX, NULL);
295 }
296
297 /*
298 * Given the list of attributes we now have in json_vps,
299 * convert them into a JSON document and append it to the
300 * return cursor.
301 */
302 MEM(vb = fr_value_box_alloc_null(ctx));
303
304 json_str = fr_json_afrom_pair_list(vb, &json_vps, format);
305 if (!json_str) {
306 REDEBUG("Failed to generate JSON string");
307 goto error;
308 }
309 fr_value_box_bstrdup_buffer_shallow(NULL, vb, NULL, json_str, false);
310
312 fr_pair_list_free(&json_vps);
313
314 return XLAT_ACTION_DONE;
315}
316
317/** Pre-parse and validate literal jpath expressions for maps
318 *
319 * @param[in] cs #CONF_SECTION that defined the map instance.
320 * @param[in] mod_inst module instance (unused).
321 * @param[in] proc_inst the cache structure to fill.
322 * @param[in] src Where to get the JSON data from.
323 * @param[in] maps set of maps to translate to jpaths.
324 * @return
325 * - 0 on success.
326 * - -1 on failure.
327 */
328static int mod_map_proc_instantiate(CONF_SECTION *cs, UNUSED void const *mod_inst, void *proc_inst,
329 tmpl_t const *src, map_list_t const *maps)
330{
331 rlm_json_jpath_cache_t *cache_inst = proc_inst;
332 map_t const *map = NULL;
333 ssize_t slen;
334 rlm_json_jpath_cache_t *cache = cache_inst, **tail = &cache->next;
335
336 if (!src) {
337 cf_log_err(cs, "Missing JSON source");
338
339 return -1;
340 }
341
342 while ((map = map_list_next(maps, map))) {
343 CONF_PAIR *cp = cf_item_to_pair(map->ci);
344 char const *p;
345
346#ifndef HAVE_JSON_OBJECT_GET_INT64
347 if (tmpl_is_attr(map->lhs) && (tmpl_attr_tail_da(map->lhs)->type == FR_TYPE_UINT64)) {
348 cf_log_err(cp, "64bit integers are not supported by linked json-c. "
349 "Upgrade to json-c >= 0.10 to use this feature");
350 return -1;
351 }
352#endif
353
354 switch (map->rhs->type) {
356 p = map->rhs->name;
357 slen = fr_jpath_parse(cache, &cache->jpath, p, map->rhs->len);
358 if (slen <= 0) {
359 error:
360 cf_canonicalize_error(cp, slen, "Syntax error", fr_strerror());
361 return -1;
362 }
363 break;
364
365 case TMPL_TYPE_DATA:
366 if (tmpl_value_type(map->rhs) != FR_TYPE_STRING) {
367 cf_log_err(cp, "Right side of map must be a string");
368 return -1;
369 }
370 p = tmpl_value(map->rhs)->vb_strvalue;
371 slen = fr_jpath_parse(cache, &cache->jpath, p, tmpl_value_length(map->rhs));
372 if (slen <= 0) goto error;
373 break;
374
375 default:
376 continue;
377 }
378
379 /*
380 * Slightly weird... This is here because our first
381 * list member was pre-allocated and passed to the
382 * instantiation callback.
383 */
384 if (map_list_next(maps, map)) {
385 *tail = cache = talloc_zero(cache, rlm_json_jpath_cache_t);
386 tail = &cache->next;
387 }
388 }
389
390 return 0;
391}
392
393/** Converts a string value into a #fr_pair_t
394 *
395 * @param[in,out] ctx to allocate #fr_pair_t (s).
396 * @param[out] out where to write the resulting #fr_pair_t.
397 * @param[in] request The current request.
398 * @param[in] map to process.
399 * @param[in] uctx The json tree/jpath expression to evaluate.
400 * @return
401 * - 0 on success.
402 * - -1 on failure.
403 */
404static int _json_map_proc_get_value(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request,
405 map_t const *map, void *uctx)
406{
407 fr_pair_t *vp;
408 rlm_json_jpath_to_eval_t *to_eval = uctx;
410 fr_value_box_list_t head;
411 int ret;
412
414 fr_value_box_list_init(&head);
415
416 ret = fr_jpath_evaluate_leaf(request, &head, tmpl_attr_tail_da(map->lhs)->type, tmpl_attr_tail_da(map->lhs),
417 to_eval->root, to_eval->jpath);
418 if (ret < 0) {
419 RPEDEBUG("Failed evaluating jpath");
420 return -1;
421 }
422 if (ret == 0) return 0;
423 fr_assert(!fr_value_box_list_empty(&head));
424
425 for (value = fr_value_box_list_head(&head);
426 value;
427 fr_pair_append(out, vp), value = fr_value_box_list_next(&head, value)) {
429
430 if (fr_value_box_steal(vp, &vp->data, value) < 0) {
431 RPEDEBUG("Copying data to attribute failed");
434 return -1;
435 }
436 }
437
438 return 0;
439}
440
441/** Parses a JSON string, and executes jpath queries against it to map values to attributes
442 *
443 * @param p_result Result of applying map:
444 * - #RLM_MODULE_NOOP no rows were returned or columns matched.
445 * - #RLM_MODULE_UPDATED if one or more #fr_pair_t were added to the #request_t.
446 * - #RLM_MODULE_FAIL if a fault occurred.
447 * @param mod_inst unused.
448 * @param proc_inst cached jpath sequences.
449 * @param request The current request.
450 * @param json JSON string to parse.
451 * @param maps Head of the map list.
452 * @return UNLANG_ACTION_CALCULATE_RESULT
453 */
454static unlang_action_t mod_map_proc(rlm_rcode_t *p_result, UNUSED void const *mod_inst, void *proc_inst, request_t *request,
455 fr_value_box_list_t *json, map_list_t const *maps)
456{
458 struct json_tokener *tok;
459
460 rlm_json_jpath_cache_t *cache = proc_inst;
461 map_t const *map = NULL;
462
464
465 char const *json_str = NULL;
466 fr_value_box_t *json_head = fr_value_box_list_head(json);
467
468 if (!json_head) {
469 REDEBUG("JSON map input cannot be (null)");
471 }
472
474 json_head, json, FR_TYPE_STRING,
476 SIZE_MAX) < 0) {
477 REDEBUG("Failed concatenating input");
479 }
480 json_str = json_head->vb_strvalue;
481
482 if ((talloc_array_length(json_str) - 1) == 0) {
483 REDEBUG("JSON map input length must be > 0");
485 }
486
487 tok = json_tokener_new();
488 to_eval.root = json_tokener_parse_ex(tok, json_str, (int)(talloc_array_length(json_str) - 1));
489 if (!to_eval.root) {
490 REMARKER(json_str, tok->char_offset, "%s", json_tokener_error_desc(json_tokener_get_error(tok)));
491 rcode = RLM_MODULE_FAIL;
492 goto finish;
493 }
494
495 while ((map = map_list_next(maps, map))) {
496 switch (map->rhs->type) {
497 /*
498 * Cached types
499 */
501 case TMPL_TYPE_DATA:
502 to_eval.jpath = cache->jpath;
503
504 if (map_to_request(request, map, _json_map_proc_get_value, &to_eval) < 0) {
505 rcode = RLM_MODULE_FAIL;
506 goto finish;
507 }
508 cache = cache->next;
509 break;
510
511 /*
512 * Dynamic types
513 */
514 default:
515 {
516 ssize_t slen;
517 fr_jpath_node_t *node;
518 char *to_parse;
519
520 if (tmpl_aexpand(request, &to_parse, request, map->rhs, fr_jpath_escape_func, NULL) < 0) {
521 RPERROR("Failed getting jpath data");
522 rcode = RLM_MODULE_FAIL;
523 goto finish;
524 }
525 slen = fr_jpath_parse(request, &node, to_parse, talloc_array_length(to_parse) - 1);
526 if (slen <= 0) {
527 REMARKER(to_parse, -(slen), "%s", fr_strerror());
528 talloc_free(to_parse);
529 rcode = RLM_MODULE_FAIL;
530 goto finish;
531 }
532 to_eval.jpath = node;
533
534 if (map_to_request(request, map, _json_map_proc_get_value, &to_eval) < 0) {
535 talloc_free(node);
536 talloc_free(to_parse);
537 rcode = RLM_MODULE_FAIL;
538 goto finish;
539 }
540 talloc_free(node);
541 }
542 break;
543 }
544 }
545
546
547finish:
548 json_object_put(to_eval.root);
549 json_tokener_free(tok);
550
551 RETURN_MODULE_RCODE(rcode);
552}
553
554static int mod_instantiate(module_inst_ctx_t const *mctx)
555{
556 rlm_json_t const *inst = talloc_get_type_abort(mctx->mi->data, rlm_json_t);
557 CONF_SECTION *conf = mctx->mi->conf;
558 fr_json_format_t *format = inst->format;
559
560 /*
561 * Check the output format type and warn on unused
562 * format options
563 */
565 if (format->output_mode == JSON_MODE_UNSET) {
566 cf_log_err(conf, "output_mode value \"%s\" is invalid", format->output_mode_str);
567 return -1;
568 }
570
571 return 0;
572}
573
574static int mod_bootstrap(module_inst_ctx_t const *mctx)
575{
576 rlm_json_t const *inst = talloc_get_type_abort(mctx->mi->data, rlm_json_t);
577 xlat_t *xlat;
578
579 xlat = module_rlm_xlat_register(mctx->mi->boot, mctx, "encode", json_encode_xlat, FR_TYPE_STRING);
581
582 if (map_proc_register(mctx->mi->boot, inst, "json", mod_map_proc,
583 mod_map_proc_instantiate, sizeof(rlm_json_jpath_cache_t), 0) < 0) return -1;
584 return 0;
585}
586
587static int mod_load(void)
588{
589 xlat_t *xlat;
590
592
593 if (unlikely(!(xlat = xlat_func_register(NULL, "json.escape", json_escape_xlat, FR_TYPE_STRING)))) return -1;
595 if (unlikely(!(xlat = xlat_func_register(NULL, "json.quote", json_quote_xlat, FR_TYPE_STRING)))) return -1;
597 if (unlikely(!(xlat = xlat_func_register(NULL, "json.jpath_validate", json_jpath_validate_xlat, FR_TYPE_STRING)))) return -1;
599
600 return 0;
601}
602
603static void mod_unload(void)
604{
605 xlat_func_unregister("json.escape");
606 xlat_func_unregister("json.quote");
607 xlat_func_unregister("json.jpath_validate");
608}
609
610/*
611 * The module name should be the only globally exported symbol.
612 * That is, everything else should be 'static'.
613 *
614 * If the module needs to temporarily modify it's instantiation
615 * data, the type should be changed to MODULE_TYPE_THREAD_UNSAFE.
616 * The server will then take care of ensuring that the module
617 * is single-threaded.
618 */
621 .common = {
622 .magic = MODULE_MAGIC_INIT,
623 .name = "json",
624 .onload = mod_load,
625 .unload = mod_unload,
627 .inst_size = sizeof(rlm_json_t),
628 .bootstrap = mod_bootstrap,
630 }
631};
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:483
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:209
#define unlikely(_x)
Definition build.h:381
#define UNUSED
Definition build.h:315
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:642
#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:297
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:579
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:664
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:289
#define cf_canonicalize_error(_ci, _slen, _msg, _str)
Definition cf_util.h:367
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:36
static fr_slen_t in
Definition dict.h:824
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:205
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:1239
@ 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:459
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:559
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:1781
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:131
@ 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:257
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:283
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:1826
#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_MODULE_RCODE(_rcode)
Definition rcode.h:64
#define RETURN_MODULE_FAIL
Definition rcode.h:56
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:42
@ RLM_MODULE_UPDATED
OK (pairs modified).
Definition rcode.h:49
fr_dict_attr_t const * request_attr_request
Definition request.c:45
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:587
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:328
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:574
static void mod_unload(void)
Definition rlm_json.c:603
rlm_json_jpath_cache_t * next
Next jpath cache entry.
Definition rlm_json.c:74
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:620
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:404
static unlang_action_t mod_map_proc(rlm_rcode_t *p_result, UNUSED void const *mod_inst, void *proc_inst, request_t *request, fr_value_box_list_t *json, map_list_t const *maps)
Parses a JSON string, and executes jpath queries against it to map values to attributes.
Definition rlm_json.c:454
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition rlm_json.c:554
static conf_parser_t const module_config[]
Definition rlm_json.c:62
rlm_json module instance
Definition rlm_json.c:57
static int instantiate(module_inst_ctx_t const *mctx)
Definition rlm_rest.c:1310
int fr_sbuff_reset_talloc(fr_sbuff_t *sbuff)
Reset a talloced buffer to its initial length, clearing any data stored.
Definition sbuff.c:454
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:2088
#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_extend(_sbuff_or_marker)
#define fr_sbuff_used(_sbuff_or_marker)
#define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:329
void * data
Module's instance data.
Definition module.h:271
void * boot
Data allocated during the boostrap phase.
Definition module.h:274
conf_parser_t const * config
How to convert a CONF_SECTION to a module instance.
Definition module.h:198
#define tmpl_value_length(_tmpl)
Definition tmpl.h:949
static fr_slen_t vpt
Definition tmpl.h:1272
#define tmpl_value(_tmpl)
Definition tmpl.h:948
#define tmpl_is_attr(vpt)
Definition tmpl.h:213
@ TMPL_TYPE_DATA
Value in native boxed format.
Definition tmpl.h:142
@ TMPL_TYPE_DATA_UNRESOLVED
Unparsed literal string.
Definition tmpl.h:183
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:798
ssize_t tmpl_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err, tmpl_t **out, fr_sbuff_t *name, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Parse a string into a TMPL_TYPE_ATTR_* type tmpl_t.
#define tmpl_value_type(_tmpl)
Definition tmpl.h:950
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
Definition tmpl.h:812
#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:1070
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:341
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:282
fr_type_t type
Type to cast argument to.
Definition xlat.h:155
bool required
Argument must be present, and non-empty.
Definition xlat.h:148
static fr_slen_t head
Definition xlat.h:422
#define XLAT_ARG_PARSER_TERMINATOR
Definition xlat.h:168
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:147
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:70
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:43
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:554
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:4014
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:3927
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:3858
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:4148
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:4253
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:5777
@ FR_VALUE_BOX_LIST_FREE
Definition value.h:221
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
Definition value.h:632
#define fr_value_box_list_foreach(_list_head, _iter)
Definition value.h:206
int format(printf, 5, 0))
static size_t char ** out
Definition value.h:997
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:365
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:218
void xlat_func_unregister(char const *name)
Unregister an xlat function.
Definition xlat_func.c:519