The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
rlm_exec.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: df686ac20dd52cb713408744c3b9b5792302c7e4 $
19  * @file rlm_exec.c
20  * @brief Execute commands and parse the results.
21  *
22  * @copyright 2002,2006 The FreeRADIUS server project
23  * @copyright 2002 Alan DeKok (aland@freeradius.org)
24  */
25 RCSID("$Id: df686ac20dd52cb713408744c3b9b5792302c7e4 $")
26 
27 #define LOG_PREFIX mctx->inst->name
28 
29 #include <stdint.h>
30 
31 #include <freeradius-devel/server/log.h>
32 #include <freeradius-devel/server/module_rlm.h>
33 #include <freeradius-devel/server/tmpl.h>
34 #include <freeradius-devel/server/exec.h>
35 #include <freeradius-devel/server/main_config.h>
36 #include <freeradius-devel/unlang/interpret.h>
37 #include <freeradius-devel/unlang/call_env.h>
38 #include <freeradius-devel/util/debug.h>
39 #include <freeradius-devel/util/token.h>
40 #include <freeradius-devel/server/pairmove.h>
41 #include <freeradius-devel/unlang/xlat_func.h>
42 #include <freeradius-devel/unlang/xlat.h>
43 #include <freeradius-devel/unlang/module.h>
44 
45 /*
46  * Define a structure for our module configuration.
47  */
48 typedef struct {
49  bool wait;
56 } rlm_exec_t;
57 
58 static const conf_parser_t module_config[] = {
59  { FR_CONF_OFFSET("wait", rlm_exec_t, wait), .dflt = "yes" },
60  { FR_CONF_OFFSET("input_pairs", rlm_exec_t, input_list) },
61  { FR_CONF_OFFSET("output_pairs", rlm_exec_t, output_list) },
62  { FR_CONF_OFFSET("shell_escape", rlm_exec_t, shell_escape), .dflt = "yes" },
63  { FR_CONF_OFFSET("env_inherit", rlm_exec_t, env_inherit), .dflt = "no" },
66 };
67 
68 typedef struct {
71 
74  .env = (call_env_parser_t[]){
77  }
78 };
79 
81  xlat_ctx_t const *xctx,
82  request_t *request, UNUSED fr_value_box_list_t *in)
83 {
84  fr_exec_state_t *exec = talloc_get_type_abort(xctx->rctx, fr_exec_state_t);
85  fr_value_box_t *vb;
86 
87  if (exec->failed == FR_EXEC_FAIL_TIMEOUT) {
88  RPEDEBUG("Execution of external program failed");
89  return XLAT_ACTION_FAIL;
90  }
91 
92  /*
93  * Allow a return code of 3 as success to match the behaviour of
94  * inline module calls.
95  */
96  if ((exec->status != 0) && (exec->status != 3)) {
97  RPEDEBUG("Execution of external program returned %d", exec->status);
98  return XLAT_ACTION_FAIL;
99  }
100 
101  MEM(vb = fr_value_box_alloc_null(ctx));
102 
103  /*
104  * Remove any trailing line endings and trim buffer
105  */
107  fr_sbuff_trim_talloc(&exec->stdout_buff, SIZE_MAX);
108 
109  /*
110  * Use the buffer for the output vb
111  */
112  fr_value_box_strdup_shallow(vb, NULL, fr_sbuff_buff(&exec->stdout_buff), true);
113 
114  fr_dcursor_append(out, vb);
115 
116  return XLAT_ACTION_DONE;
117 }
118 
120  { .required = true, .type = FR_TYPE_STRING },
121  { .variadic = XLAT_ARG_VARIADIC_EMPTY_KEEP, .type = FR_TYPE_VOID},
123 };
124 
125 /** Exec programs from an xlat
126  *
127  * Example:
128 @verbatim
129 %exec('/bin/echo', 'hello') == "hello"
130 @endverbatim
131  *
132  * Exactly one request is consumed during the process lifetime,
133  * after which the process exits.
134  *
135  * @ingroup xlat_functions
136  */
138  xlat_ctx_t const *xctx,
139  request_t *request, fr_value_box_list_t *in)
140 {
142  fr_pair_list_t *env_pairs = NULL;
143  fr_exec_state_t *exec;
144 
145  if (inst->input_list) {
146  env_pairs = tmpl_list_head(request, tmpl_list(inst->input_list));
147  if (!env_pairs) {
148  REDEBUG("Failed to find input pairs for xlat");
149  return XLAT_ACTION_FAIL;
150  }
151  }
152 
153  if (!inst->wait) {
154  if (unlikely(fr_exec_oneshot_nowait(request, in, env_pairs, inst->shell_escape, inst->env_inherit) < 0)) {
155  RPEDEBUG("Failed executing program");
156  return XLAT_ACTION_FAIL;
157  }
158 
159  return XLAT_ACTION_DONE;
160  }
161 
162  MEM(exec = talloc_zero(unlang_interpret_frame_talloc_ctx(request), fr_exec_state_t));
163  if (fr_exec_oneshot(exec, exec, request,
164  in,
165  env_pairs, inst->shell_escape, inst->env_inherit,
166  false,
167  inst->wait, ctx,
168  inst->timeout) < 0) {
169  talloc_free(exec);
170  return XLAT_ACTION_FAIL;
171  }
172 
173  return unlang_xlat_yield(request, exec_xlat_oneshot_wait_resume, NULL, 0, exec);
174 }
175 
176 typedef struct {
177  fr_value_box_list_t box;
178  int status;
180 
181 static const rlm_rcode_t status2rcode[] = {
182  [0] = RLM_MODULE_OK,
183  [1] = RLM_MODULE_REJECT,
184  [2] = RLM_MODULE_FAIL,
185  [3] = RLM_MODULE_OK,
186  [4] = RLM_MODULE_HANDLED,
187  [5] = RLM_MODULE_INVALID,
188  [6] = RLM_MODULE_DISALLOW,
189  [7] = RLM_MODULE_NOTFOUND,
190  [8] = RLM_MODULE_NOOP,
191  [9] = RLM_MODULE_UPDATED,
192 };
193 
194 
195 /** Process the exit code returned by one of the exec functions
196  *
197  * @param request Current request.
198  * @param box Output string from exec call.
199  * @param status code returned by exec call.
200  * @return One of the RLM_MODULE_* values.
201  */
202 static rlm_rcode_t rlm_exec_status2rcode(request_t *request, fr_value_box_t *box, int status)
203 {
204  rlm_rcode_t rcode;
205 
206  if (status < 0) return RLM_MODULE_FAIL;
207 
208  /*
209  * Exec'd programs are meant to return exit statuses that correspond
210  * to the standard RLM_MODULE_* + 1.
211  *
212  * This frees up 0, for success where it'd normally be reject.
213  */
214  if (status == 0) {
215  RDEBUG("Program executed successfully");
216 
217  return RLM_MODULE_OK;
218  }
219 
220  if (status > 9) {
221  REDEBUG("Program returned invalid code (greater than max rcode) (%i > 9): %pV",
222  status, box);
223  return RLM_MODULE_FAIL;
224  }
225 
226  rcode = status2rcode[status];
227 
228  if (rcode == RLM_MODULE_FAIL) {
229  if (box) RDEBUG("Program failed with output: %pV", box);
230 
231  return RLM_MODULE_FAIL;
232  }
233 
234  return rcode;
235 }
236 
237 /** Resume a request after xlat expansion.
238  *
239  */
241  request_t *request)
242 {
244  fr_value_box_list_t *args = talloc_get_type_abort(mctx->rctx, fr_value_box_list_t);
245  fr_pair_list_t *env_pairs = NULL;
246 
247  /*
248  * Decide what input/output the program takes.
249  */
250  if (inst->input_list) {
251  env_pairs = tmpl_list_head(request, tmpl_list(inst->input_list));
252  if (!env_pairs) {
254  }
255  }
256 
257  if (unlikely(fr_exec_oneshot_nowait(request, args, env_pairs, inst->shell_escape, inst->env_inherit) < 0)) {
258  RPEDEBUG("Failed executing program");
260  }
261 
263 }
264 
265 static fr_sbuff_parse_rules_t const rhs_term = {
266  .escapes = &(fr_sbuff_unescape_rules_t){
267  .chr = '\\',
268  .do_hex = true,
269  .do_oct = false
270  },
271  .terminals = &FR_SBUFF_TERMS(
272  L(""),
273  L("\t"),
274  L("\n"),
275  L(","),
276  )
277 };
278 
279 /** Process the exit code and output of a short lived process
280  *
281  */
283 {
284  int status;
286  rlm_exec_ctx_t *m = talloc_get_type_abort(mctx->rctx, rlm_exec_ctx_t);
287  rlm_rcode_t rcode;
288 
289  /*
290  * Also prints stdout as an error if there was any...
291  */
292  rcode = rlm_exec_status2rcode(request, fr_value_box_list_head(&m->box), m->status);
293  switch (rcode) {
294  case RLM_MODULE_OK:
295  case RLM_MODULE_UPDATED:
296  if (inst->output_list && !fr_value_box_list_empty(&m->box)) {
297  ssize_t slen;
298  map_t *map;
299  fr_value_box_t *box = fr_value_box_list_head(&m->box);
300  fr_sbuff_t in = FR_SBUFF_IN(box->vb_strvalue, box->vb_length);
301  tmpl_rules_t lhs_rules = (tmpl_rules_t) {
302  .attr = {
303  .dict_def = request->dict,
304  .prefix = TMPL_ATTR_REF_PREFIX_AUTO,
305  .list_def = tmpl_list(inst->output_list),
306  .list_presence = TMPL_ATTR_LIST_ALLOW,
307 
308  /*
309  * Otherwise the tmpl code returns 0 when asked
310  * to parse unknown names. So we say "please
311  * parse unknown names as unresolved attributes",
312  * and then do a second pass to complain that the
313  * thing isn't known.
314  */
315  .allow_unresolved = false
316  }
317  };
318  tmpl_rules_t rhs_rules = lhs_rules;
319 
321  rhs_rules.attr.list_def = request_attr_request;
322  rhs_rules.at_runtime = true;
323  rhs_rules.xlat.runtime_el = unlang_interpret_event_list(request);
324 
325  while (true) {
326  slen = map_afrom_substr(request, &map, NULL, &in,
328  &lhs_rules, &rhs_rules, &rhs_term);
329  if (slen < 0) {
330  RPEDEBUG("Failed parsing exec output string");
331  break;
332  }
333  if (!slen) {
334  RDEBUG("Stopping due to no input at %.*s", (int) fr_sbuff_remaining(&in), fr_sbuff_current(&in));
335  break;
336  }
337 
338 #ifdef STATIC_ANALYZER
339  if (!map) return -1;
340 #endif
341 
342  RDEBUG("applying %s %s %s",
343  map->lhs->name, fr_tokens[map->op], map->rhs->name);
344 
345  if (radius_legacy_map_apply(request, map, NULL) < 0) {
346  RPEDEBUG("Failed applying assignment");
347 
348  TALLOC_FREE(map);
349  return -1;
350  }
351  TALLOC_FREE(map);
352 
353  fr_sbuff_adv_past_whitespace(&in, SIZE_MAX, NULL);
354 
355  if (!fr_sbuff_remaining(&in)) break;
356 
357  /*
358  * Allow commas between attributes
359  */
360  (void) fr_sbuff_next_if_char(&in, ',');
361  }
362  }
363  break;
364 
365  default:
366  break;
367  }
368 
369  status = m->status;
370  if (status < 0) {
371  REDEBUG("Program exited with signal %d", -status);
373  }
374 
375  /*
376  * The status rcodes aren't quite the same as the rcode
377  * enumeration.
378  */
379  RETURN_MODULE_RCODE(rcode);
380 }
381 
382 /** Dispatch one request using a short lived process
383  *
384  */
385 static unlang_action_t CC_HINT(nonnull) mod_exec_dispatch_oneshot(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
386 {
387  rlm_exec_ctx_t *m;
388  fr_pair_list_t *env_pairs = NULL;
389  TALLOC_CTX *ctx;
391  exec_call_env_t *env_data = talloc_get_type_abort(mctx->env_data, exec_call_env_t);
392 
393  if (!env_data->program) {
394  RDEBUG("This module requires 'program' to be set.");
396  }
397 
398  /*
399  * Get frame-local talloc ctx
400  */
401  ctx = unlang_interpret_frame_talloc_ctx(request);
402 
403  /*
404  * Do the asynchronous xlat expansion.
405  */
406  if (!inst->wait) {
407  fr_value_box_list_t *box = talloc_zero(ctx, fr_value_box_list_t);
408 
409  fr_value_box_list_init(box);
410 
411  /*
412  * The xlat here only expands the arguments, then calls
413  * the resume function we set to actually dispatch the
414  * exec request.
415  */
416  return unlang_module_yield_to_xlat(request, NULL, box, request, tmpl_xlat(env_data->program),
417  mod_exec_oneshot_nowait_resume, NULL, 0, box);
418  }
419 
420  /*
421  * Decide what input/output the program takes.
422  */
423  if (inst->input_list) {
424  env_pairs = tmpl_list_head(request, tmpl_list(inst->input_list));
425  if (!env_pairs) RETURN_MODULE_INVALID;
426  }
427 
428  if (inst->output_list) {
429  if (!tmpl_list_head(request, tmpl_list(inst->output_list))) {
431  }
432  }
433 
434  MEM(m = talloc_zero(ctx, rlm_exec_ctx_t));
435  m->status = 2; /* Fail if we couldn't exec */
436 
437  fr_value_box_list_init(&m->box);
438  return unlang_module_yield_to_tmpl(m, &m->box,
439  request, env_data->program,
440  TMPL_ARGS_EXEC(env_pairs, inst->timeout, true, &m->status),
442  NULL, 0, &m->box);
443 }
444 
445 /*
446  * Do any per-module initialization that is separate to each
447  * configured instance of the module. e.g. set up connections
448  * to external databases, read configuration files, set up
449  * dictionary entries, etc.
450  *
451  * If configuration information is given in the config section
452  * that must be referenced in later calls, store a handle to it
453  * in *instance otherwise put a null pointer there.
454  */
455 static int mod_bootstrap(module_inst_ctx_t const *mctx)
456 {
457  rlm_exec_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_exec_t);
458  CONF_SECTION *conf = mctx->inst->conf;
459  xlat_t *xlat;
460 
463 
464  if (inst->input_list && !tmpl_is_list(inst->input_list)) {
465  cf_log_perr(conf, "Invalid input list '%s'", inst->input_list->name);
466  return -1;
467  }
468 
469  if (inst->output_list && !tmpl_is_list(inst->output_list)) {
470  cf_log_err(conf, "Invalid output list '%s'", inst->output_list->name);
471  return -1;
472  }
473 
474  /*
475  * Sanity check the config. If we're told to NOT wait,
476  * then the output pairs must not be defined.
477  */
478  if (!inst->wait && (inst->output_list != NULL)) {
479  cf_log_err(conf, "Cannot read output pairs if wait = no");
480  return -1;
481  }
482 
483  if (!inst->timeout_is_set || !fr_time_delta_ispos(inst->timeout)) {
484  /*
485  * Pick the shorter one
486  */
490  }
491  else {
492  if (fr_time_delta_lt(inst->timeout, fr_time_delta_from_sec(1))) {
493  cf_log_err(conf, "Timeout '%pVs' is too small (minimum: 1s)", fr_box_time_delta(inst->timeout));
494  return -1;
495  }
496 
497  /*
498  * Blocking a request longer than max_request_time isn't going to help anyone.
499  */
501  cf_log_err(conf, "Timeout '%pVs' is too large (maximum: %pVs)",
503  return -1;
504  }
505  }
506 
507  return 0;
508 }
509 
510 /*
511  * The module name should be the only globally exported symbol.
512  * That is, everything else should be 'static'.
513  *
514  * If the module needs to temporarily modify it's instantiation
515  * data, the type should be changed to MODULE_TYPE_THREAD_UNSAFE.
516  * The server will then take care of ensuring that the module
517  * is single-threaded.
518  */
519 extern module_rlm_t rlm_exec;
521  .common = {
522  .magic = MODULE_MAGIC_INIT,
523  .name = "exec",
524  .flags = MODULE_TYPE_THREAD_SAFE,
525  .inst_size = sizeof(rlm_exec_t),
527  .bootstrap = mod_bootstrap,
528  },
529  .method_names = (module_method_name_t[]){
530  { .name1 = CF_IDENT_ANY, .name2 = CF_IDENT_ANY, .method = mod_exec_dispatch_oneshot,
531  .method_env = &exec_method_env },
533  }
534 };
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition: action.h:35
va_list args
Definition: acutest.h:770
#define RCSID(id)
Definition: build.h:444
#define L(_str)
Helper for initialising arrays of string literals.
Definition: build.h:207
#define unlikely(_x)
Definition: build.h:378
#define UNUSED
Definition: build.h:313
#define CALL_ENV_TERMINATOR
Definition: call_env.h:212
#define FR_CALL_ENV_METHOD_OUT(_inst)
Helper macro for populating the size/type fields of a call_env_method_t from the output structure typ...
Definition: call_env.h:216
@ CALL_ENV_FLAG_FORCE_QUOTE
Force quote method when parsing tmpl.
Definition: call_env.h:79
#define FR_CALL_ENV_PARSE_ONLY_OFFSET(_name, _cast_type, _flags, _struct, _parse_field)
Specify a call_env_parser_t which writes out the result of the parsing phase to the field specified.
Definition: call_env.h:365
Per method call config.
Definition: call_env.h:171
#define CONF_PARSER_TERMINATOR
Definition: cf_parse.h:626
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition: cf_parse.h:268
#define FR_CONF_OFFSET_IS_SET(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct,...
Definition: cf_parse.h:282
Defines a CONF_PAIR to C data type mapping.
Definition: cf_parse.h:563
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:89
#define cf_log_err(_cf, _fmt,...)
Definition: cf_util.h:265
#define cf_log_perr(_cf, _fmt,...)
Definition: cf_util.h:272
#define CF_IDENT_ANY
Definition: cf_util.h:78
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
Definition: dcursor.h:405
static fr_time_delta_t timeout
Definition: dhcpclient.c:54
static fr_slen_t in
Definition: dict.h:645
void *_CONST data
Module instance's parsed configuration.
Definition: dl_module.h:165
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition: dl_module.h:65
CONF_SECTION *_CONST conf
Module's instance configuration.
Definition: dl_module.h:166
int fr_exec_oneshot(TALLOC_CTX *ctx, fr_exec_state_t *exec, request_t *request, fr_value_box_list_t *args, fr_pair_list_t *env_pairs, bool env_escape, bool env_inherit, bool need_stdin, bool store_stdout, TALLOC_CTX *stdout_ctx, fr_time_delta_t timeout)
Call an child program, optionally reading it's output.
Definition: exec.c:984
int fr_exec_oneshot_nowait(request_t *request, fr_value_box_list_t *args, fr_pair_list_t *env_pairs, bool env_escape, bool env_inherit)
Similar to fr_exec_oneshot, but does not attempt to parse output.
Definition: exec.c:623
#define EXEC_TIMEOUT
Default wait time for exec calls (in seconds).
Definition: exec.h:32
@ FR_EXEC_FAIL_TIMEOUT
Definition: exec.h:50
fr_sbuff_t stdout_buff
Expandable buffer to store process output.
Definition: exec.h:54
int status
return code of the program
Definition: exec.h:76
fr_exec_fail_t failed
what kind of failure
Definition: exec.h:74
static xlat_action_t exec_xlat_oneshot(TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Exec programs from an xlat.
Definition: rlm_exec.c:137
fr_event_list_t * unlang_interpret_event_list(request_t *request)
Get the event list for the current interpreter.
Definition: interpret.c:1745
TALLOC_CTX * unlang_interpret_frame_talloc_ctx(request_t *request)
Get a talloc_ctx which is valid only for this frame.
Definition: interpret.c:1384
#define RPEDEBUG(fmt,...)
Definition: log.h:376
fr_table_num_sorted_t const map_assignment_op_table[]
Definition: map.c:330
ssize_t map_afrom_substr(TALLOC_CTX *ctx, map_t **out, map_t **parent_p, fr_sbuff_t *in, fr_table_num_sorted_t const *op_table, size_t op_table_len, tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules, fr_sbuff_parse_rules_t const *p_rules)
Parse sbuff into (which may contain refs) to map_t.
Definition: map.c:428
size_t map_assignment_op_table_len
Definition: map.c:346
talloc_free(reap)
main_config_t const * main_config
Main server configuration.
Definition: main_config.c:69
fr_time_delta_t max_request_time
How long a request can be processed for before timing out.
Definition: main_config.h:61
@ TMPL_ATTR_REF_PREFIX_AUTO
Attribute refs may have a '&' prefix.
Definition: merged_model.c:231
@ TMPL_ATTR_REF_PREFIX_YES
Attribute refs must have '&' prefix.
Definition: merged_model.c:229
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
Definition: merged_model.c:113
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ FR_TYPE_VOID
User data.
Definition: merged_model.c:127
long int ssize_t
Definition: merged_model.c:24
void * env_data
Per call environment data.
Definition: module_ctx.h:44
void * rctx
Resume ctx that a module previously set.
Definition: module_ctx.h:45
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:52
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:42
Temporary structure to hold arguments for module calls.
Definition: module_ctx.h:41
Temporary structure to hold arguments for instantiation calls.
Definition: module_ctx.h:51
Specifies a module method identifier.
Definition: module_method.c:36
module_t common
Common fields presented by all modules.
Definition: module_rlm.h:37
int radius_legacy_map_apply(request_t *request, map_t const *map, fr_edit_list_t *el)
Move a map using the operators from the old pairmove functionality.
Definition: pairmove.c:507
static const conf_parser_t config[]
Definition: base.c:188
#define REDEBUG(fmt,...)
Definition: radclient.h:52
#define RDEBUG(fmt,...)
Definition: radclient.h:53
static rs_t * conf
Definition: radsniff.c:53
#define RETURN_MODULE_RCODE(_rcode)
Definition: rcode.h:64
#define RETURN_MODULE_INVALID
Definition: rcode.h:59
#define RETURN_MODULE_OK
Definition: rcode.h:57
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
@ RLM_MODULE_INVALID
The module considers the request invalid.
Definition: rcode.h:45
@ RLM_MODULE_OK
The module is OK, continue.
Definition: rcode.h:43
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition: rcode.h:42
@ RLM_MODULE_DISALLOW
Reject the request (user is locked out).
Definition: rcode.h:46
@ RLM_MODULE_REJECT
Immediately reject the request.
Definition: rcode.h:41
@ RLM_MODULE_NOTFOUND
User not found.
Definition: rcode.h:47
@ RLM_MODULE_UPDATED
OK (pairs modified).
Definition: rcode.h:49
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
Definition: rcode.h:48
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
Definition: rcode.h:44
fr_dict_attr_t const * request_attr_request
Definition: request.c:41
static xlat_action_t exec_xlat_oneshot_wait_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, UNUSED fr_value_box_list_t *in)
Definition: rlm_exec.c:80
static unlang_action_t mod_exec_oneshot_nowait_resume(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Resume a request after xlat expansion.
Definition: rlm_exec.c:240
fr_time_delta_t timeout
Definition: rlm_exec.c:54
bool shell_escape
Definition: rlm_exec.c:52
static rlm_rcode_t rlm_exec_status2rcode(request_t *request, fr_value_box_t *box, int status)
Process the exit code returned by one of the exec functions.
Definition: rlm_exec.c:202
module_rlm_t rlm_exec
Definition: rlm_exec.c:520
static const rlm_rcode_t status2rcode[]
Definition: rlm_exec.c:181
tmpl_t * input_list
Definition: rlm_exec.c:50
static int mod_bootstrap(module_inst_ctx_t const *mctx)
Definition: rlm_exec.c:455
bool timeout_is_set
Definition: rlm_exec.c:55
tmpl_t * output_list
Definition: rlm_exec.c:51
fr_value_box_list_t box
Definition: rlm_exec.c:177
static unlang_action_t mod_exec_dispatch_oneshot(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Dispatch one request using a short lived process.
Definition: rlm_exec.c:385
static const call_env_method_t exec_method_env
Definition: rlm_exec.c:72
static unlang_action_t mod_exec_oneshot_wait_resume(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Process the exit code and output of a short lived process.
Definition: rlm_exec.c:282
static xlat_arg_parser_t const exec_xlat_args[]
Definition: rlm_exec.c:119
bool wait
Definition: rlm_exec.c:49
static const conf_parser_t module_config[]
Definition: rlm_exec.c:58
bool env_inherit
Definition: rlm_exec.c:53
static fr_sbuff_parse_rules_t const rhs_term
Definition: rlm_exec.c:265
tmpl_t * program
Definition: rlm_exec.c:69
int fr_sbuff_trim_talloc(fr_sbuff_t *sbuff, size_t len)
Trim a talloced sbuff to the minimum length required to represent the contained string.
Definition: sbuff.c:399
bool const sbuff_char_line_endings[UINT8_MAX+1]
Definition: sbuff.c:96
size_t fr_sbuff_trim(fr_sbuff_t *sbuff, bool const to_trim[static UINT8_MAX+1])
Trim trailing characters from a string we're composing.
Definition: sbuff.c:2087
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:2047
#define FR_SBUFF_IN(_start, _len_or_end)
#define fr_sbuff_adv_past_whitespace(_sbuff, _len, _tt)
#define fr_sbuff_current(_sbuff_or_marker)
#define FR_SBUFF_TERMS(...)
Initialise a terminal structure with a list of sorted strings.
Definition: sbuff.h:167
#define fr_sbuff_buff(_sbuff_or_marker)
#define fr_sbuff_remaining(_sbuff_or_marker)
Set of parsing rules for *unescape_until functions.
Definition: merged_model.c:163
@ MODULE_TYPE_THREAD_SAFE
Module is threadsafe.
Definition: module.h:49
#define MODULE_NAME_TERMINATOR
Definition: module.h:135
#define tmpl_xlat(_tmpl)
Definition: tmpl.h:925
fr_pair_list_t * tmpl_list_head(request_t *request, fr_dict_attr_t const *list)
Resolve attribute fr_pair_list_t value to an attribute list.
Definition: tmpl_eval.c:74
tmpl_xlat_rules_t xlat
Rules/data for parsing xlats.
Definition: tmpl.h:345
bool at_runtime
Produce an ephemeral/runtime tmpl.
Definition: tmpl.h:353
static bool tmpl_is_list(tmpl_t const *vpt)
Definition: tmpl.h:915
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Definition: tmpl.h:344
@ TMPL_ATTR_LIST_ALLOW
Attribute refs are allowed to have a list.
Definition: tmpl.h:274
struct tmpl_rules_s tmpl_rules_t
Definition: tmpl.h:236
static fr_dict_attr_t const * tmpl_list(tmpl_t const *vpt)
Definition: tmpl.h:899
fr_event_list_t * runtime_el
The eventlist to use for runtime instantiation of xlats.
Definition: tmpl.h:333
Optional arguments passed to vp_tmpl functions.
Definition: tmpl.h:341
unlang_action_t unlang_module_yield_to_xlat(TALLOC_CTX *ctx, bool *p_success, fr_value_box_list_t *out, request_t *request, xlat_exp_head_t const *exp, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
Push a pre-compiled xlat and resumption state onto the stack for evaluation.
Definition: module.c:449
unlang_action_t unlang_module_yield_to_tmpl(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request, tmpl_t const *vpt, unlang_tmpl_args_t *args, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
Push a pre-compiled tmpl and resumption state onto the stack for evaluation.
Definition: module.c:496
RETURN_MODULE_FAIL
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
Value pair map.
Definition: map.h:77
fr_token_t op
The operator that controls insertion of the dst attribute.
Definition: map.h:82
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
fr_dict_attr_t const * list_def
Default list to use with unqualified attribute reference.
Definition: tmpl.h:307
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
Definition: tmpl.h:285
tmpl_attr_prefix_t prefix
Whether the attribute reference requires a prefix.
Definition: tmpl.h:310
#define talloc_get_type_abort_const
Definition: talloc.h:270
#define fr_time_delta_lt(_a, _b)
Definition: time.h:283
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition: time.h:588
#define fr_time_delta_ispos(_a)
Definition: time.h:288
#define fr_time_delta_gt(_a, _b)
Definition: time.h:281
A time delta, a difference in time measured in nanoseconds.
Definition: time.h:80
char const * fr_tokens[T_TOKEN_LAST]
Definition: token.c:78
@ T_BACK_QUOTED_STRING
Definition: token.h:123
#define TMPL_ARGS_EXEC(_env, _timeout, _stdout_on_error, _status_out)
Create a temporary argument structure for evaluating an exec type tmpl.
Definition: tmpl.h:75
xlat_action_t unlang_xlat_yield(request_t *request, xlat_func_t resume, xlat_func_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
Definition: xlat.c:561
bool required
Argument must be present, and non-empty.
Definition: xlat.h:146
@ XLAT_ARG_VARIADIC_EMPTY_KEEP
Empty argument groups are left alone, and either passed through as empty groups or null boxes.
Definition: xlat.h:137
#define XLAT_ARG_PARSER_TERMINATOR
Definition: xlat.h:166
xlat_action_t
Definition: xlat.h:35
@ XLAT_ACTION_FAIL
An xlat function failed.
Definition: xlat.h:42
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition: xlat.h:41
Definition for a single argument consumend by an xlat function.
Definition: xlat.h:145
void fr_value_box_strdup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Assign a buffer containing a nul terminated string to a box, but don't copy it.
Definition: value.c:3985
#define fr_box_time_delta(_val)
Definition: value.h:336
int nonnull(2, 5))
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
Definition: value.h:619
static size_t char ** out
Definition: value.h:984
void * rctx
Resume context.
Definition: xlat_ctx.h:47
module_ctx_t const * mctx
Synthesised module calling ctx.
Definition: xlat_ctx.h:45
An xlat calling ctx.
Definition: xlat_ctx.h:42
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
Definition: xlat_func.c:360
xlat_t * xlat_func_register_module(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function for a module.
Definition: xlat_func.c:274