Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Functions | Variables
pbx_functions.c File Reference

Custom function management routines. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/cli.h"
#include "asterisk/linkedlists.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/term.h"
#include "asterisk/threadstorage.h"
#include "asterisk/xmldoc.h"
#include "pbx_private.h"
Include dependency graph for pbx_functions.c:

Go to the source code of this file.

Data Structures

struct  acf_root
 Registered functions container. More...
 

Functions

int __ast_custom_function_register (struct ast_custom_function *acf, struct ast_module *mod)
 Register a custom function. More...
 
int __ast_custom_function_register_escalating (struct ast_custom_function *acf, enum ast_custom_function_escalation escalation, struct ast_module *mod)
 Register a custom function which requires escalated privileges. More...
 
static void __init_thread_inhibit_escalations_tl (void)
 A thread local indicating whether the current thread can run 'dangerous' dialplan functions. More...
 
static int acf_retrieve_docs (struct ast_custom_function *acf)
 
struct ast_custom_functionast_custom_function_find (const char *name)
 
static struct ast_custom_functionast_custom_function_find_nolock (const char *name)
 
int ast_custom_function_unregister (struct ast_custom_function *acf)
 Unregister a custom function. More...
 
int ast_func_read (struct ast_channel *chan, const char *function, char *workspace, size_t len)
 executes a read operation on a function More...
 
int ast_func_read2 (struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen)
 executes a read operation on a function More...
 
int ast_func_write (struct ast_channel *chan, const char *function, const char *value)
 executes a write operation on a function More...
 
int ast_thread_inhibit_escalations (void)
 Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations. If pbx_live_dangerously() has been called, this function has no effect. More...
 
int ast_thread_inhibit_escalations_swap (int inhibit)
 Swap the current thread escalation inhibit setting. More...
 
static char * complete_functions (const char *word, int pos, int state)
 
static char * func_args (char *function)
 return a pointer to the arguments of the function, and terminates the function name with '\0' More...
 
static char * handle_show_function (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_show_functions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int is_read_allowed (struct ast_custom_function *acfptr)
 Determines whether execution of a custom function's read function is allowed. More...
 
static int is_write_allowed (struct ast_custom_function *acfptr)
 Determines whether execution of a custom function's write function is allowed. More...
 
int load_pbx_functions_cli (void)
 
void pbx_live_dangerously (int new_live_dangerously)
 Enable/disable the execution of 'dangerous' functions from external protocols (AMI, etc.). More...
 
static int read_escalates (const struct ast_custom_function *acf)
 Returns true if given custom function escalates privileges on read. More...
 
static int thread_inhibits_escalations (void)
 Indicates whether the current thread inhibits the execution of dangerous functions. More...
 
static void unload_pbx_functions_cli (void)
 
static int write_escalates (const struct ast_custom_function *acf)
 Returns true if given custom function escalates privileges on write. More...
 

Variables

static struct ast_cli_entry acf_cli []
 
static struct acf_root acf_root = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static int live_dangerously
 Set to true (non-zero) to globally allow all dangerous dialplan functions to run. More...
 
static struct ast_threadstorage thread_inhibit_escalations_tl = { .once = PTHREAD_ONCE_INIT , .key_init = __init_thread_inhibit_escalations_tl , .custom_init = NULL , }
 

Detailed Description

Custom function management routines.

Author
Corey Farrell git@c.nosp@m.fwar.nosp@m.e.com

Definition in file pbx_functions.c.

Function Documentation

◆ __ast_custom_function_register()

int __ast_custom_function_register ( struct ast_custom_function acf,
struct ast_module mod 
)

Register a custom function.

Definition at line 373 of file pbx_functions.c.

References acf_retrieve_docs(), ast_custom_function_find_nolock(), ast_log, AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_STATIC_DOC, ast_verb, COLOR_BRCYAN, COLORIZE, COLORIZE_FMT, ast_custom_function::docsrc, LOG_ERROR, ast_custom_function::mod, and ast_custom_function::name.

Referenced by __ast_custom_function_register_escalating(), __init_manager(), ast_msg_init(), load_features_config(), and load_pbx().

374 {
375  struct ast_custom_function *cur;
376 
377  if (!acf) {
378  return -1;
379  }
380 
381  acf->mod = mod;
382 #ifdef AST_XML_DOCS
383  acf->docsrc = AST_STATIC_DOC;
384 #endif
385 
386  if (acf_retrieve_docs(acf)) {
387  return -1;
388  }
389 
391 
393  if (cur) {
394  ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
396  return -1;
397  }
398 
399  /* Store in alphabetical order */
400  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
401  if (strcmp(acf->name, cur->name) < 0) {
402  AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
403  break;
404  }
405  }
407  if (!cur) {
408  AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
409  }
410 
412 
413  ast_verb(2, "Registered custom function '" COLORIZE_FMT "'\n", COLORIZE(COLOR_BRCYAN, 0, acf->name));
414 
415  return 0;
416 }
const char * name
Definition: pbx.h:119
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
enum ast_doc_src docsrc
Definition: pbx.h:127
static struct ast_custom_function * ast_custom_function_find_nolock(const char *name)
struct ast_module * mod
Definition: pbx.h:142
#define ast_verb(level,...)
Definition: logger.h:463
#define COLOR_BRCYAN
Definition: term.h:60
#define COLORIZE(fg, bg, str)
Definition: term.h:68
#define ast_log
Definition: astobj2.c:42
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
#define COLORIZE_FMT
Shortcut macros for coloring a set of text.
Definition: term.h:67
Registered functions container.
Definition: pbx_functions.c:59
#define AST_RWLIST_INSERT_BEFORE_CURRENT
Definition: linkedlists.h:609
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
static int acf_retrieve_docs(struct ast_custom_function *acf)
#define LOG_ERROR
Definition: logger.h:285
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:740
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616

◆ __ast_custom_function_register_escalating()

int __ast_custom_function_register_escalating ( struct ast_custom_function acf,
enum ast_custom_function_escalation  escalation,
struct ast_module mod 
)

Register a custom function which requires escalated privileges.

Examples would be SHELL() (for which a read needs permission to execute arbitrary code) or FILE() (for which write needs permission to change files on the filesystem).

Definition at line 418 of file pbx_functions.c.

References __ast_custom_function_register(), AST_CFE_BOTH, AST_CFE_NONE, AST_CFE_READ, AST_CFE_WRITE, ast_custom_function::read_escalates, and ast_custom_function::write_escalates.

419 {
420  int res;
421 
422  res = __ast_custom_function_register(acf, mod);
423  if (res != 0) {
424  return -1;
425  }
426 
427  switch (escalation) {
428  case AST_CFE_NONE:
429  break;
430  case AST_CFE_READ:
431  acf->read_escalates = 1;
432  break;
433  case AST_CFE_WRITE:
434  acf->write_escalates = 1;
435  break;
436  case AST_CFE_BOTH:
437  acf->read_escalates = 1;
438  acf->write_escalates = 1;
439  break;
440  }
441 
442  return 0;
443 }
int __ast_custom_function_register(struct ast_custom_function *acf, struct ast_module *mod)
Register a custom function.
unsigned int write_escalates
Definition: pbx.h:147
unsigned int read_escalates
Definition: pbx.h:143

◆ __init_thread_inhibit_escalations_tl()

static void __init_thread_inhibit_escalations_tl ( void  )
static

A thread local indicating whether the current thread can run 'dangerous' dialplan functions.

Definition at line 46 of file pbx_functions.c.

62 {

◆ acf_retrieve_docs()

static int acf_retrieve_docs ( struct ast_custom_function acf)
static

Definition at line 328 of file pbx_functions.c.

References ast_custom_function::arguments, ast_free, ast_module_name(), ast_string_field_init, ast_string_field_set, ast_strlen_zero, AST_XML_DOC, ast_xmldoc_build_arguments(), ast_xmldoc_build_description(), ast_xmldoc_build_seealso(), ast_xmldoc_build_synopsis(), ast_xmldoc_build_syntax(), desc, ast_custom_function::desc, ast_custom_function::docsrc, ast_custom_function::mod, ast_custom_function::name, ast_custom_function::seealso, synopsis, ast_custom_function::synopsis, and ast_custom_function::syntax.

Referenced by __ast_custom_function_register().

329 {
330 #ifdef AST_XML_DOCS
331  char *tmpxml;
332 
333  /* Let's try to find it in the Documentation XML */
334  if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) {
335  return 0;
336  }
337 
338  if (ast_string_field_init(acf, 128)) {
339  return -1;
340  }
341 
342  /* load synopsis */
343  tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod));
344  ast_string_field_set(acf, synopsis, tmpxml);
345  ast_free(tmpxml);
346 
347  /* load description */
348  tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod));
349  ast_string_field_set(acf, desc, tmpxml);
350  ast_free(tmpxml);
351 
352  /* load syntax */
353  tmpxml = ast_xmldoc_build_syntax("function", acf->name, ast_module_name(acf->mod));
354  ast_string_field_set(acf, syntax, tmpxml);
355  ast_free(tmpxml);
356 
357  /* load arguments */
358  tmpxml = ast_xmldoc_build_arguments("function", acf->name, ast_module_name(acf->mod));
359  ast_string_field_set(acf, arguments, tmpxml);
360  ast_free(tmpxml);
361 
362  /* load seealso */
363  tmpxml = ast_xmldoc_build_seealso("function", acf->name, ast_module_name(acf->mod));
364  ast_string_field_set(acf, seealso, tmpxml);
365  ast_free(tmpxml);
366 
367  acf->docsrc = AST_XML_DOC;
368 #endif
369 
370  return 0;
371 }
const char * name
Definition: pbx.h:119
static const char synopsis[]
Definition: app_mysql.c:64
const ast_string_field syntax
Definition: pbx.h:126
char * ast_xmldoc_build_description(const char *type, const char *name, const char *module)
Generate description documentation from XML.
Definition: xmldoc.c:2250
const ast_string_field desc
Definition: pbx.h:126
enum ast_doc_src docsrc
Definition: pbx.h:127
static const char desc[]
Definition: cdr_mysql.c:73
const ast_string_field arguments
Definition: pbx.h:126
struct ast_module * mod
Definition: pbx.h:142
char * ast_xmldoc_build_synopsis(const char *type, const char *name, const char *module)
Generate synopsis documentation from XML.
Definition: xmldoc.c:2227
char * ast_xmldoc_build_arguments(const char *type, const char *name, const char *module)
Generate the [arguments] tag based on type of node (&#39;application&#39;, &#39;function&#39; or &#39;agi&#39;) and name...
Definition: xmldoc.c:2075
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
#define ast_free(a)
Definition: astmm.h:182
const ast_string_field synopsis
Definition: pbx.h:126
char * ast_xmldoc_build_syntax(const char *type, const char *name, const char *module)
Get the syntax for a specified application or function.
Definition: xmldoc.c:1253
char * ast_xmldoc_build_seealso(const char *type, const char *name, const char *module)
Parse the <see-also> node content.
Definition: xmldoc.c:1698
const char * ast_module_name(const struct ast_module *mod)
Get the name of a module.
Definition: loader.c:615
const ast_string_field seealso
Definition: pbx.h:126
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ ast_custom_function_find()

struct ast_custom_function* ast_custom_function_find ( const char *  name)

Definition at line 262 of file pbx_functions.c.

References ast_custom_function_find_nolock(), AST_RWLIST_RDLOCK, and AST_RWLIST_UNLOCK.

Referenced by ast_func_read(), ast_func_read2(), ast_func_write(), and handle_show_function().

263 {
264  struct ast_custom_function *acf;
265 
269 
270  return acf;
271 }
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
static struct ast_custom_function * ast_custom_function_find_nolock(const char *name)
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
Registered functions container.
Definition: pbx_functions.c:59
static const char name[]
Definition: cdr_mysql.c:74

◆ ast_custom_function_find_nolock()

static struct ast_custom_function* ast_custom_function_find_nolock ( const char *  name)
static

Definition at line 240 of file pbx_functions.c.

References AST_RWLIST_TRAVERSE, ast_custom_function::name, and NULL.

Referenced by __ast_custom_function_register(), and ast_custom_function_find().

241 {
242  struct ast_custom_function *cur;
243  int cmp;
244 
245  AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
246  cmp = strcmp(name, cur->name);
247  if (cmp > 0) {
248  continue;
249  }
250  if (!cmp) {
251  /* Found it. */
252  break;
253  }
254  /* Not in container. */
255  cur = NULL;
256  break;
257  }
258 
259  return cur;
260 }
const char * name
Definition: pbx.h:119
#define NULL
Definition: resample.c:96
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
Registered functions container.
Definition: pbx_functions.c:59
static const char name[]
Definition: cdr_mysql.c:74

◆ ast_custom_function_unregister()

int ast_custom_function_unregister ( struct ast_custom_function acf)

Unregister a custom function.

Definition at line 273 of file pbx_functions.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_string_field_free_memory, ast_verb, AST_XML_DOC, ast_custom_function::docsrc, and ast_custom_function::name.

Referenced by load_module(), manager_shutdown(), message_shutdown(), reload(), unload_features_config(), unload_module(), unload_parking_bridge_features(), and unload_pbx().

274 {
275  struct ast_custom_function *cur;
276 
277  if (!acf) {
278  return -1;
279  }
280 
282  cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist);
283  if (cur) {
284 #ifdef AST_XML_DOCS
285  if (cur->docsrc == AST_XML_DOC) {
287  }
288 #endif
289  ast_verb(2, "Unregistered custom function %s\n", cur->name);
290  }
292 
293  return cur ? 0 : -1;
294 }
const char * name
Definition: pbx.h:119
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
enum ast_doc_src docsrc
Definition: pbx.h:127
#define ast_verb(level,...)
Definition: logger.h:463
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
Registered functions container.
Definition: pbx_functions.c:59
#define AST_RWLIST_REMOVE
Definition: linkedlists.h:884
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368

◆ ast_func_read()

int ast_func_read ( struct ast_channel chan,
const char *  function,
char *  workspace,
size_t  len 
)

executes a read operation on a function

Parameters
chanChannel to execute on
functionData containing the function call string (will be modified)
workspaceA pointer to safe memory to use for a return value
lenthe number of bytes in workspace

This application executes a function in read mode on a given channel.

Return values
0success
non-zerofailure

Definition at line 599 of file pbx_functions.c.

References __ast_module_user_add(), __ast_module_user_remove(), args, ast_copy_string(), ast_custom_function_find(), ast_free, ast_log, ast_str_buffer(), ast_str_create, ast_str_size(), ast_strdupa, copy(), func_args(), is_read_allowed(), LOG_ERROR, ast_custom_function::mod, NULL, ast_custom_function::read, ast_custom_function::read2, and str.

Referenced by action_getvar(), assign_uuid(), fetch_access_token(), fetch_google_access_token(), generate_status(), handle_getvariable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().

600 {
601  char *copy = ast_strdupa(function);
602  char *args = func_args(copy);
603  struct ast_custom_function *acfptr = ast_custom_function_find(copy);
604  int res;
605  struct ast_module_user *u = NULL;
606 
607  if (acfptr == NULL) {
608  ast_log(LOG_ERROR, "Function %s not registered\n", copy);
609  } else if (!acfptr->read && !acfptr->read2) {
610  ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
611  } else if (!is_read_allowed(acfptr)) {
612  ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy);
613  } else if (acfptr->read) {
614  if (acfptr->mod) {
615  u = __ast_module_user_add(acfptr->mod, chan);
616  }
617  res = acfptr->read(chan, copy, args, workspace, len);
618  if (acfptr->mod && u) {
619  __ast_module_user_remove(acfptr->mod, u);
620  }
621 
622  return res;
623  } else {
624  struct ast_str *str = ast_str_create(16);
625 
626  if (acfptr->mod) {
627  u = __ast_module_user_add(acfptr->mod, chan);
628  }
629  res = acfptr->read2(chan, copy, args, &str, 0);
630  if (acfptr->mod && u) {
631  __ast_module_user_remove(acfptr->mod, u);
632  }
633  ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len);
634  ast_free(str);
635 
636  return res;
637  }
638 
639  return -1;
640 }
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition: strings.h:699
static int is_read_allowed(struct ast_custom_function *acfptr)
Determines whether execution of a custom function&#39;s read function is allowed.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
void __ast_module_user_remove(struct ast_module *, struct ast_module_user *)
Definition: loader.c:826
static int copy(char *infile, char *outfile)
Utility function to copy a file.
struct ast_module * mod
Definition: pbx.h:142
const char * str
Definition: app_jack.c:147
const char * args
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
static char * func_args(char *function)
return a pointer to the arguments of the function, and terminates the function name with &#39;\0&#39; ...
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
struct ast_module_user * __ast_module_user_add(struct ast_module *, struct ast_channel *)
Definition: loader.c:800
#define LOG_ERROR
Definition: logger.h:285
ast_acf_read2_fn_t read2
Definition: pbx.h:137
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_free(a)
Definition: astmm.h:182
struct ast_custom_function * ast_custom_function_find(const char *name)
ast_acf_read_fn_t read
Definition: pbx.h:129
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ ast_func_read2()

int ast_func_read2 ( struct ast_channel chan,
const char *  function,
struct ast_str **  str,
ssize_t  maxlen 
)

executes a read operation on a function

Parameters
chanChannel to execute on
functionData containing the function call string (will be modified)
strA dynamic string buffer into which to place the result.
maxlen<0 if the dynamic buffer should not grow; >0 if the dynamic buffer should be limited to that number of bytes; 0 if the dynamic buffer has no upper limit

This application executes a function in read mode on a given channel.

Return values
0success
non-zerofailure

Definition at line 642 of file pbx_functions.c.

References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log, ast_str_buffer(), ast_str_make_space, ast_str_reset(), ast_str_size(), ast_strdupa, copy(), func_args(), is_read_allowed(), LOG_ERROR, maxsize, ast_custom_function::mod, NULL, ast_custom_function::read, ast_custom_function::read2, ast_custom_function::read_max, and VAR_BUF_SIZE.

Referenced by ast_ari_channels_get_channel_var(), ast_str_substitute_variables_full(), AST_TEST_DEFINE(), and channel_get_external_vars().

643 {
644  char *copy = ast_strdupa(function);
645  char *args = func_args(copy);
646  struct ast_custom_function *acfptr = ast_custom_function_find(copy);
647  int res;
648  struct ast_module_user *u = NULL;
649 
650  if (acfptr == NULL) {
651  ast_log(LOG_ERROR, "Function %s not registered\n", copy);
652  } else if (!acfptr->read && !acfptr->read2) {
653  ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
654  } else if (!is_read_allowed(acfptr)) {
655  ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy);
656  } else {
657  if (acfptr->mod) {
658  u = __ast_module_user_add(acfptr->mod, chan);
659  }
660  ast_str_reset(*str);
661  if (acfptr->read2) {
662  /* ast_str enabled */
663  res = acfptr->read2(chan, copy, args, str, maxlen);
664  } else {
665  /* Legacy function pointer, allocate buffer for result */
666  int maxsize = ast_str_size(*str);
667 
668  if (maxlen > -1) {
669  if (maxlen == 0) {
670  if (acfptr->read_max) {
671  maxsize = acfptr->read_max;
672  } else {
673  maxsize = VAR_BUF_SIZE;
674  }
675  } else {
676  maxsize = maxlen;
677  }
678  ast_str_make_space(str, maxsize);
679  }
680  res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
681  }
682  if (acfptr->mod && u) {
683  __ast_module_user_remove(acfptr->mod, u);
684  }
685 
686  return res;
687  }
688 
689  return -1;
690 }
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition: strings.h:699
static int is_read_allowed(struct ast_custom_function *acfptr)
Determines whether execution of a custom function&#39;s read function is allowed.
#define ast_str_make_space(buf, new_len)
Definition: strings.h:780
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
void __ast_module_user_remove(struct ast_module *, struct ast_module_user *)
Definition: loader.c:826
static int copy(char *infile, char *outfile)
Utility function to copy a file.
struct ast_module * mod
Definition: pbx.h:142
const char * args
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
static char * func_args(char *function)
return a pointer to the arguments of the function, and terminates the function name with &#39;\0&#39; ...
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
size_t read_max
Definition: pbx.h:139
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
struct ast_module_user * __ast_module_user_add(struct ast_module *, struct ast_channel *)
Definition: loader.c:800
#define LOG_ERROR
Definition: logger.h:285
ast_acf_read2_fn_t read2
Definition: pbx.h:137
#define VAR_BUF_SIZE
Definition: pbx_private.h:68
static int maxsize
struct ast_custom_function * ast_custom_function_find(const char *name)
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:653
ast_acf_read_fn_t read
Definition: pbx.h:129

◆ ast_func_write()

int ast_func_write ( struct ast_channel chan,
const char *  function,
const char *  value 
)

executes a write operation on a function

Parameters
chanChannel to execute on
functionData containing the function call string (will be modified)
valueA value parameter to pass for writing

This application executes a function in write mode on a given channel.

Return values
0success
non-zerofailure

Definition at line 692 of file pbx_functions.c.

References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log, ast_strdupa, copy(), func_args(), is_write_allowed(), LOG_ERROR, ast_custom_function::mod, NULL, and ast_custom_function::write.

Referenced by ast_channel_hangupcause_hash_set(), AST_TEST_DEFINE(), chanavail_exec(), conf_run(), confbridge_exec(), fetch_google_access_token(), pbx_builtin_pushvar_helper(), pbx_builtin_setvar_helper(), setup_profile_bridge(), setup_profile_caller(), and setup_profile_paged().

693 {
694  char *copy = ast_strdupa(function);
695  char *args = func_args(copy);
696  struct ast_custom_function *acfptr = ast_custom_function_find(copy);
697 
698  if (acfptr == NULL) {
699  ast_log(LOG_ERROR, "Function %s not registered\n", copy);
700  } else if (!acfptr->write) {
701  ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
702  } else if (!is_write_allowed(acfptr)) {
703  ast_log(LOG_ERROR, "Dangerous function %s write blocked\n", copy);
704  } else {
705  int res;
706  struct ast_module_user *u = NULL;
707 
708  if (acfptr->mod) {
709  u = __ast_module_user_add(acfptr->mod, chan);
710  }
711  res = acfptr->write(chan, copy, args, value);
712  if (acfptr->mod && u) {
713  __ast_module_user_remove(acfptr->mod, u);
714  }
715 
716  return res;
717  }
718 
719  return -1;
720 }
void __ast_module_user_remove(struct ast_module *, struct ast_module_user *)
Definition: loader.c:826
static int copy(char *infile, char *outfile)
Utility function to copy a file.
struct ast_module * mod
Definition: pbx.h:142
static int is_write_allowed(struct ast_custom_function *acfptr)
Determines whether execution of a custom function&#39;s write function is allowed.
const char * args
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
#define ast_log
Definition: astobj2.c:42
static char * func_args(char *function)
return a pointer to the arguments of the function, and terminates the function name with &#39;\0&#39; ...
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
ast_acf_write_fn_t write
Definition: pbx.h:141
struct ast_module_user * __ast_module_user_add(struct ast_module *, struct ast_channel *)
Definition: loader.c:800
#define LOG_ERROR
Definition: logger.h:285
struct ast_custom_function * ast_custom_function_find(const char *name)

◆ ast_thread_inhibit_escalations()

int ast_thread_inhibit_escalations ( void  )

Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations. If pbx_live_dangerously() has been called, this function has no effect.

Returns
0 if successfuly marked current thread.
Non-zero if marking current thread failed.

Definition at line 479 of file pbx_functions.c.

References ast_log, ast_threadstorage_get(), LOG_ERROR, NULL, and thread_inhibit_escalations_tl.

Referenced by ast_add_extension2_lockopt(), and handle_tcptls_connection().

480 {
481  int *thread_inhibit_escalations;
482 
483  thread_inhibit_escalations = ast_threadstorage_get(
484  &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
485  if (thread_inhibit_escalations == NULL) {
486  ast_log(LOG_ERROR, "Error inhibiting privilege escalations for current thread\n");
487  return -1;
488  }
489 
490  *thread_inhibit_escalations = 1;
491  return 0;
492 }
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
static struct ast_threadstorage thread_inhibit_escalations_tl
Definition: pbx_functions.c:46

◆ ast_thread_inhibit_escalations_swap()

int ast_thread_inhibit_escalations_swap ( int  inhibit)

Swap the current thread escalation inhibit setting.

Since
11.24.0
Parameters
inhibitNew setting. Non-zero to inhibit.
Return values
1if dangerous function execution was inhibited.
0if dangerous function execution was allowed.
-1on error.

Definition at line 494 of file pbx_functions.c.

References ast_log, ast_threadstorage_get(), LOG_ERROR, NULL, and thread_inhibit_escalations_tl.

Referenced by ast_add_extension2_lockopt().

495 {
496  int *thread_inhibit_escalations;
497  int orig;
498 
499  thread_inhibit_escalations = ast_threadstorage_get(
500  &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
501  if (thread_inhibit_escalations == NULL) {
502  ast_log(LOG_ERROR, "Error swapping privilege escalations inhibit for current thread\n");
503  return -1;
504  }
505 
506  orig = *thread_inhibit_escalations;
507  *thread_inhibit_escalations = !!inhibit;
508  return orig;
509 }
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
static struct ast_threadstorage thread_inhibit_escalations_tl
Definition: pbx_functions.c:46

◆ complete_functions()

static char* complete_functions ( const char *  word,
int  pos,
int  state 
)
static

Definition at line 105 of file pbx_functions.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, ast_custom_function::name, and NULL.

Referenced by handle_show_function().

106 {
107  struct ast_custom_function *cur;
108  char *ret = NULL;
109  int which = 0;
110  int wordlen;
111  int cmp;
112 
113  if (pos != 3) {
114  return NULL;
115  }
116 
117  wordlen = strlen(word);
119  AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
120  /*
121  * Do a case-insensitive search for convenience in this
122  * 'complete' function.
123  *
124  * We must search the entire container because the functions are
125  * sorted and normally found case sensitively.
126  */
127  cmp = strncasecmp(word, cur->name, wordlen);
128  if (!cmp) {
129  /* Found match. */
130  if (++which <= state) {
131  /* Not enough matches. */
132  continue;
133  }
134  ret = ast_strdup(cur->name);
135  break;
136  }
137  }
139 
140  return ret;
141 }
const char * name
Definition: pbx.h:119
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
Registered functions container.
Definition: pbx_functions.c:59
short word

◆ func_args()

static char* func_args ( char *  function)
static

return a pointer to the arguments of the function, and terminates the function name with '\0'

Definition at line 448 of file pbx_functions.c.

References args, ast_log, and LOG_WARNING.

Referenced by ast_func_read(), ast_func_read2(), ast_func_write(), and read_pjsip().

449 {
450  char *args = strchr(function, '(');
451 
452  if (!args) {
453  ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses. Assuming null argument.\n", function);
454  } else {
455  char *p;
456  *args++ = '\0';
457  if ((p = strrchr(args, ')'))) {
458  *p = '\0';
459  } else {
460  ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args);
461  }
462  }
463  return args;
464 }
#define LOG_WARNING
Definition: logger.h:274
const char * args
#define ast_log
Definition: astobj2.c:42

◆ handle_show_function()

static char* handle_show_function ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 143 of file pbx_functions.c.

References ast_cli_args::argc, ast_custom_function::arguments, ast_cli_args::argv, ast_cli(), ast_custom_function_find(), ast_free, ast_malloc, AST_MAX_APP, AST_TERM_MAX_ESCAPE_CHARS, AST_XML_DOC, ast_xmldoc_printable(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, COLOR_CYAN, COLOR_MAGENTA, ast_cli_entry::command, complete_functions(), ast_custom_function::desc, ast_custom_function::docsrc, ast_cli_args::fd, sip_to_pjsip::info(), ast_cli_args::n, ast_custom_function::name, NULL, ast_cli_args::pos, S_OR, ast_custom_function::seealso, synopsis, ast_custom_function::synopsis, ast_custom_function::syntax, term_color(), ast_cli_entry::usage, and ast_cli_args::word.

144 {
145  struct ast_custom_function *acf;
146  /* Maximum number of characters added by terminal coloring is 22 */
147  char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40];
148  char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL;
149  char stxtitle[40], *syntax = NULL, *arguments = NULL;
150  int syntax_size, description_size, synopsis_size, arguments_size, seealso_size;
151 
152  switch (cmd) {
153  case CLI_INIT:
154  e->command = "core show function";
155  e->usage =
156  "Usage: core show function <function>\n"
157  " Describe a particular dialplan function.\n";
158  return NULL;
159  case CLI_GENERATE:
160  return complete_functions(a->word, a->pos, a->n);
161  }
162 
163  if (a->argc != 4) {
164  return CLI_SHOWUSAGE;
165  }
166 
167  if (!(acf = ast_custom_function_find(a->argv[3]))) {
168  ast_cli(a->fd, "No function by that name registered.\n");
169 
170  return CLI_FAILURE;
171  }
172 
173  syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
174  syntax = ast_malloc(syntax_size);
175  if (!syntax) {
176  ast_cli(a->fd, "Memory allocation failure!\n");
177 
178  return CLI_FAILURE;
179  }
180 
181  snprintf(info, sizeof(info), "\n -= Info about function '%s' =- \n\n", acf->name);
182  term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
183  term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
184  term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
185  term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
186  term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
187  term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
188  term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
189 #ifdef AST_XML_DOCS
190  if (acf->docsrc == AST_XML_DOC) {
191  arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1);
192  synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1);
193  description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1);
194  seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1);
195  } else
196 #endif
197  {
198  synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
199  synopsis = ast_malloc(synopsis_size);
200 
201  description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
202  description = ast_malloc(description_size);
203 
204  arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
205  arguments = ast_malloc(arguments_size);
206 
207  seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
208  seealso = ast_malloc(seealso_size);
209 
210  /* check allocated memory. */
211  if (!synopsis || !description || !arguments || !seealso) {
212  ast_free(synopsis);
213  ast_free(description);
214  ast_free(arguments);
215  ast_free(seealso);
216  ast_free(syntax);
217 
218  return CLI_FAILURE;
219  }
220 
221  term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
222  term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
223  term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size);
224  term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
225  }
226 
227  ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
228  infotitle, syntitle, synopsis, destitle, description,
229  stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
230 
231  ast_free(arguments);
232  ast_free(synopsis);
233  ast_free(description);
234  ast_free(seealso);
235  ast_free(syntax);
236 
237  return CLI_SUCCESS;
238 }
const char * name
Definition: pbx.h:119
static const char synopsis[]
Definition: app_mysql.c:64
const ast_string_field syntax
Definition: pbx.h:126
const int argc
Definition: cli.h:160
#define COLOR_CYAN
Definition: term.h:59
const ast_string_field desc
Definition: pbx.h:126
enum ast_doc_src docsrc
Definition: pbx.h:127
Definition: cli.h:152
const ast_string_field arguments
Definition: pbx.h:126
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define AST_TERM_MAX_ESCAPE_CHARS
Maximum number of characters needed for a color escape sequence, and another one for a trailing reset...
Definition: term.h:71
const int fd
Definition: cli.h:159
const int n
Definition: cli.h:165
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
static char * complete_functions(const char *word, int pos, int state)
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
Definition: term.c:184
const char *const * argv
Definition: cli.h:161
#define AST_MAX_APP
Definition: pbx.h:40
#define CLI_SHOWUSAGE
Definition: cli.h:45
def info(msg)
#define CLI_FAILURE
Definition: cli.h:46
#define ast_free(a)
Definition: astmm.h:182
char * command
Definition: cli.h:186
struct ast_custom_function * ast_custom_function_find(const char *name)
const char * word
Definition: cli.h:163
char * ast_xmldoc_printable(const char *bwinput, int withcolors)
Colorize and put delimiters (instead of tags) to the xmldoc output.
Definition: xmldoc.c:242
const ast_string_field synopsis
Definition: pbx.h:126
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
const int pos
Definition: cli.h:164
const ast_string_field seealso
Definition: pbx.h:126
#define COLOR_MAGENTA
Definition: term.h:57

◆ handle_show_functions()

static char* handle_show_functions ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 61 of file pbx_functions.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_custom_function::name, NULL, S_OR, ast_custom_function::synopsis, ast_custom_function::syntax, and ast_cli_entry::usage.

62 {
63  struct ast_custom_function *acf;
64  int count_acf = 0;
65  int like = 0;
66 
67  switch (cmd) {
68  case CLI_INIT:
69  e->command = "core show functions [like]";
70  e->usage =
71  "Usage: core show functions [like <text>]\n"
72  " List builtin functions, optionally only those matching a given string\n";
73  return NULL;
74  case CLI_GENERATE:
75  return NULL;
76  }
77 
78  if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) {
79  like = 1;
80  } else if (a->argc != 3) {
81  return CLI_SHOWUSAGE;
82  }
83 
84  ast_cli(a->fd, "%s Custom Functions:\n"
85  "--------------------------------------------------------------------------------\n",
86  like ? "Matching" : "Installed");
87 
89  AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
90  if (!like || strstr(acf->name, a->argv[4])) {
91  count_acf++;
92  ast_cli(a->fd, "%-20.20s %-35.35s %s\n",
93  S_OR(acf->name, ""),
94  S_OR(acf->syntax, ""),
95  S_OR(acf->synopsis, ""));
96  }
97  }
99 
100  ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
101 
102  return CLI_SUCCESS;
103 }
const char * name
Definition: pbx.h:119
const ast_string_field syntax
Definition: pbx.h:126
const int argc
Definition: cli.h:160
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
const int fd
Definition: cli.h:159
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
Registered functions container.
Definition: pbx_functions.c:59
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * command
Definition: cli.h:186
const ast_string_field synopsis
Definition: pbx.h:126
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79

◆ is_read_allowed()

static int is_read_allowed ( struct ast_custom_function acfptr)
static

Determines whether execution of a custom function's read function is allowed.

Parameters
acfptrCustom function to check
Returns
True (non-zero) if reading is allowed.
False (zero) if reading is not allowed.

Definition at line 541 of file pbx_functions.c.

References ast_debug, live_dangerously, ast_custom_function::name, read_escalates(), and thread_inhibits_escalations().

Referenced by ast_func_read(), and ast_func_read2().

542 {
543  if (!acfptr) {
544  return 1;
545  }
546 
547  if (!read_escalates(acfptr)) {
548  return 1;
549  }
550 
552  return 1;
553  }
554 
555  if (live_dangerously) {
556  /* Global setting overrides the thread's preference */
557  ast_debug(2, "Reading %s from a dangerous context\n",
558  acfptr->name);
559  return 1;
560  }
561 
562  /* We have no reason to allow this function to execute */
563  return 0;
564 }
const char * name
Definition: pbx.h:119
static int live_dangerously
Set to true (non-zero) to globally allow all dangerous dialplan functions to run. ...
Definition: pbx_functions.c:46
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
static int thread_inhibits_escalations(void)
Indicates whether the current thread inhibits the execution of dangerous functions.
static int read_escalates(const struct ast_custom_function *acf)
Returns true if given custom function escalates privileges on read.

◆ is_write_allowed()

static int is_write_allowed ( struct ast_custom_function acfptr)
static

Determines whether execution of a custom function's write function is allowed.

Parameters
acfptrCustom function to check
Returns
True (non-zero) if writing is allowed.
False (zero) if writing is not allowed.

Definition at line 574 of file pbx_functions.c.

References ast_debug, live_dangerously, ast_custom_function::name, thread_inhibits_escalations(), and write_escalates().

Referenced by ast_func_write().

575 {
576  if (!acfptr) {
577  return 1;
578  }
579 
580  if (!write_escalates(acfptr)) {
581  return 1;
582  }
583 
585  return 1;
586  }
587 
588  if (live_dangerously) {
589  /* Global setting overrides the thread's preference */
590  ast_debug(2, "Writing %s from a dangerous context\n",
591  acfptr->name);
592  return 1;
593  }
594 
595  /* We have no reason to allow this function to execute */
596  return 0;
597 }
const char * name
Definition: pbx.h:119
static int live_dangerously
Set to true (non-zero) to globally allow all dangerous dialplan functions to run. ...
Definition: pbx_functions.c:46
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
static int thread_inhibits_escalations(void)
Indicates whether the current thread inhibits the execution of dangerous functions.
static int write_escalates(const struct ast_custom_function *acf)
Returns true if given custom function escalates privileges on write.

◆ load_pbx_functions_cli()

int load_pbx_functions_cli ( void  )

Provided by pbx_functions.c

Definition at line 732 of file pbx_functions.c.

References ARRAY_LEN, ast_cli_register_multiple, ast_register_cleanup(), and unload_pbx_functions_cli().

Referenced by asterisk_daemon().

733 {
736 
737  return 0;
738 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static void unload_pbx_functions_cli(void)
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
static struct ast_cli_entry acf_cli[]

◆ pbx_live_dangerously()

void pbx_live_dangerously ( int  new_live_dangerously)

Enable/disable the execution of 'dangerous' functions from external protocols (AMI, etc.).

These dialplan functions (such as SHELL) provide an opportunity for privilege escalation. They are okay to invoke from the dialplan, but external protocols with permission controls should not normally invoke them.

This function can globally enable/disable the execution of dangerous functions from external protocols.

Parameters
new_live_dangerouslyIf true, enable the execution of escalating functions from external protocols.

Definition at line 466 of file pbx_functions.c.

References ast_log, live_dangerously, LOG_NOTICE, and LOG_WARNING.

Referenced by load_asterisk_conf().

467 {
468  if (new_live_dangerously && !live_dangerously) {
469  ast_log(LOG_WARNING, "Privilege escalation protection disabled!\n"
470  "See https://wiki.asterisk.org/wiki/x/1gKfAQ for more details.\n");
471  }
472 
473  if (!new_live_dangerously && live_dangerously) {
474  ast_log(LOG_NOTICE, "Privilege escalation protection enabled.\n");
475  }
476  live_dangerously = new_live_dangerously;
477 }
static int live_dangerously
Set to true (non-zero) to globally allow all dangerous dialplan functions to run. ...
Definition: pbx_functions.c:46
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
#define LOG_NOTICE
Definition: logger.h:263

◆ read_escalates()

static int read_escalates ( const struct ast_custom_function acf)
static

Returns true if given custom function escalates privileges on read.

Parameters
acfCustom function to query.
Returns
True (non-zero) if reads escalate privileges.
False (zero) if reads just read.

Definition at line 303 of file pbx_functions.c.

References ast_custom_function::read_escalates.

Referenced by is_read_allowed().

304 {
305  return acf->read_escalates;
306 }
unsigned int read_escalates
Definition: pbx.h:143

◆ thread_inhibits_escalations()

static int thread_inhibits_escalations ( void  )
static

Indicates whether the current thread inhibits the execution of dangerous functions.

Returns
True (non-zero) if dangerous function execution is inhibited.
False (zero) if dangerous function execution is allowed.

Definition at line 518 of file pbx_functions.c.

References ast_log, ast_threadstorage_get(), LOG_ERROR, NULL, and thread_inhibit_escalations_tl.

Referenced by is_read_allowed(), and is_write_allowed().

519 {
520  int *thread_inhibit_escalations;
521 
522  thread_inhibit_escalations = ast_threadstorage_get(
523  &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
524  if (thread_inhibit_escalations == NULL) {
525  ast_log(LOG_ERROR, "Error checking thread's ability to run dangerous functions\n");
526  /* On error, assume that we are inhibiting */
527  return 1;
528  }
529 
530  return *thread_inhibit_escalations;
531 }
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
static struct ast_threadstorage thread_inhibit_escalations_tl
Definition: pbx_functions.c:46

◆ unload_pbx_functions_cli()

static void unload_pbx_functions_cli ( void  )
static

Definition at line 727 of file pbx_functions.c.

References ARRAY_LEN, and ast_cli_unregister_multiple().

Referenced by load_pbx_functions_cli().

728 {
730 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
static struct ast_cli_entry acf_cli[]

◆ write_escalates()

static int write_escalates ( const struct ast_custom_function acf)
static

Returns true if given custom function escalates privileges on write.

Parameters
acfCustom function to query.
Returns
True (non-zero) if writes escalate privileges.
False (zero) if writes just write.

Definition at line 315 of file pbx_functions.c.

References ast_custom_function::write_escalates.

Referenced by is_write_allowed().

316 {
317  return acf->write_escalates;
318 }
unsigned int write_escalates
Definition: pbx.h:147

Variable Documentation

◆ acf_cli

struct ast_cli_entry acf_cli[]
static
Initial value:
= {
{ .handler = handle_show_functions , .summary = "Shows registered dialplan functions" ,},
{ .handler = handle_show_function , .summary = "Describe a specific dialplan function" ,},
}
static char * handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_functions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pbx_functions.c:61

Definition at line 722 of file pbx_functions.c.

◆ acf_root

struct acf_root acf_root = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
static

◆ live_dangerously

int live_dangerously
static

Set to true (non-zero) to globally allow all dangerous dialplan functions to run.

Definition at line 46 of file pbx_functions.c.

Referenced by is_read_allowed(), is_write_allowed(), load_asterisk_conf(), and pbx_live_dangerously().

◆ thread_inhibit_escalations_tl

struct ast_threadstorage thread_inhibit_escalations_tl = { .once = PTHREAD_ONCE_INIT , .key_init = __init_thread_inhibit_escalations_tl , .custom_init = NULL , }
static