Asterisk - The Open Source Telephony Project GIT-master-a358458
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.

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 */
401 if (strcmp(acf->name, cur->name) < 0) {
403 break;
404 }
405 }
407 if (!cur) {
408 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
409 }
410
412
413 ast_verb(5, "Registered custom function '" COLORIZE_FMT "'\n", COLORIZE(COLOR_BRCYAN, 0, acf->name));
414
415 return 0;
416}
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
#define ast_verb(level,...)
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:545
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:617
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:741
#define AST_RWLIST_INSERT_BEFORE_CURRENT
Definition: linkedlists.h:610
static struct ast_custom_function * ast_custom_function_find_nolock(const char *name)
static int acf_retrieve_docs(struct ast_custom_function *acf)
Registered functions container.
Definition: pbx_functions.c:59
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
struct ast_module * mod
Definition: pbx.h:142
enum ast_doc_src docsrc
Definition: pbx.h:127
const char * name
Definition: pbx.h:119
#define COLOR_BRCYAN
Definition: term.h:63
#define COLORIZE(fg, bg, str)
Definition: term.h:72
#define COLORIZE_FMT
Shortcut macros for coloring a set of text.
Definition: term.h:71
@ AST_STATIC_DOC
Definition: xmldoc.h:32

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().

◆ __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.

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}
@ AST_CFE_NONE
Definition: pbx.h:1549
@ AST_CFE_READ
Definition: pbx.h:1550
@ AST_CFE_WRITE
Definition: pbx.h:1551
@ AST_CFE_BOTH
Definition: pbx.h:1552
int __ast_custom_function_register(struct ast_custom_function *acf, struct ast_module *mod)
Register a custom function.
unsigned int read_escalates
Definition: pbx.h:143
unsigned int write_escalates
Definition: pbx.h:147

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

◆ __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.

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}
#define ast_free(a)
Definition: astmm.h:180
static const char desc[]
Definition: cdr_radius.c:84
static char * synopsis
Definition: func_enum.c:154
const char * ast_module_name(const struct ast_module *mod)
Get the name of a module.
Definition: loader.c:615
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
const ast_string_field desc
Definition: pbx.h:126
const ast_string_field synopsis
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:2271
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:1252
char * ast_xmldoc_build_arguments(const char *type, const char *name, const char *module)
Generate the [arguments] tag based on type of node ('application', 'function' or 'agi') and name.
Definition: xmldoc.c:2084
char * ast_xmldoc_build_synopsis(const char *type, const char *name, const char *module)
Generate synopsis documentation from XML.
Definition: xmldoc.c:2248
@ AST_XML_DOC
Definition: xmldoc.h:31
char * ast_xmldoc_build_seealso(const char *type, const char *name, const char *module)
Parse the <see-also> node content.
Definition: xmldoc.c:1702

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().

◆ ast_custom_function_find()

struct ast_custom_function * ast_custom_function_find ( const char *  name)

Definition at line 262 of file pbx_functions.c.

263{
264 struct ast_custom_function *acf;
265
269
270 return acf;
271}
static const char name[]
Definition: format_mp3.c:68
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78

References ast_custom_function_find_nolock(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, and name.

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

◆ 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.

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}
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:494
#define NULL
Definition: resample.c:96

References AST_RWLIST_TRAVERSE, name, ast_custom_function::name, and NULL.

Referenced by __ast_custom_function_register(), and ast_custom_function_find().

◆ 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.

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(5, "Unregistered custom function %s\n", cur->name);
290 }
292
293 return cur ? 0 : -1;
294}
#define AST_RWLIST_REMOVE
Definition: linkedlists.h:885
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374

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 __unload_module(), close_logger(), geoloc_dialplan_unload(), load_module(), manager_shutdown(), message_shutdown(), reload(), unload_features_config(), unload_module(), unload_parking_bridge_features(), and unload_pbx().

◆ 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.

600{
601 char *copy = ast_strdupa(function);
602 char *args = func_args(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 }
634 ast_free(str);
635
636 return res;
637 }
638
639 return -1;
640}
const char * str
Definition: app_jack.c:147
static int copy(char *infile, char *outfile)
Utility function to copy a file.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
struct ast_module_user * __ast_module_user_add(struct ast_module *, struct ast_channel *)
Definition: loader.c:800
void __ast_module_user_remove(struct ast_module *, struct ast_module_user *)
Definition: loader.c:826
static int is_read_allowed(struct ast_custom_function *acfptr)
Determines whether execution of a custom function's read function is allowed.
struct ast_custom_function * ast_custom_function_find(const char *name)
static char * func_args(char *function)
return a pointer to the arguments of the function, and terminates the function name with '\0'
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition: strings.h:742
ast_acf_read_fn_t read
Definition: pbx.h:129
ast_acf_read2_fn_t read2
Definition: pbx.h:137
struct ast_channel * chan
Definition: loader.c:128
Support for dynamic strings.
Definition: strings.h:623
const char * args

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, ast_module_user::chan, copy(), func_args(), is_read_allowed(), len(), 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_eval_function(), handle_getvariable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full_location().

◆ 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.

643{
644 char *copy = ast_strdupa(function);
645 char *args = func_args(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 }
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 {
674 }
675 } else {
676 maxsize = maxlen;
677 }
679 }
680 res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
681 ast_str_update(*str); /* Manually set the string length */
682 }
683 if (acfptr->mod && u) {
684 __ast_module_user_remove(acfptr->mod, u);
685 }
686
687 return res;
688 }
689
690 return -1;
691}
static int maxsize
#define VAR_BUF_SIZE
Definition: pbx_private.h:68
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:693
#define ast_str_make_space(buf, new_len)
Definition: strings.h:828
void ast_str_update(struct ast_str *buf)
Update the length of the buffer, after using ast_str merely as a buffer.
Definition: strings.h:703
size_t read_max
Definition: pbx.h:139

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_str_update(), ast_strdupa, ast_module_user::chan, 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, str, and VAR_BUF_SIZE.

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

◆ 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 693 of file pbx_functions.c.

694{
695 char *copy = ast_strdupa(function);
696 char *args = func_args(copy);
698
699 if (acfptr == NULL) {
700 ast_log(LOG_ERROR, "Function %s not registered\n", copy);
701 } else if (!acfptr->write) {
702 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
703 } else if (!is_write_allowed(acfptr)) {
704 ast_log(LOG_ERROR, "Dangerous function %s write blocked\n", copy);
705 } else {
706 int res;
707 struct ast_module_user *u = NULL;
708
709 if (acfptr->mod) {
710 u = __ast_module_user_add(acfptr->mod, chan);
711 }
712 res = acfptr->write(chan, copy, args, value);
713 if (acfptr->mod && u) {
714 __ast_module_user_remove(acfptr->mod, u);
715 }
716
717 return res;
718 }
719
720 return -1;
721}
static int is_write_allowed(struct ast_custom_function *acfptr)
Determines whether execution of a custom function's write function is allowed.
ast_acf_write_fn_t write
Definition: pbx.h:141
int value
Definition: syslog.c:37

References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log, ast_strdupa, ast_module_user::chan, copy(), func_args(), is_write_allowed(), LOG_ERROR, ast_custom_function::mod, NULL, value, 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().

◆ 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.

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}
static struct ast_threadstorage thread_inhibit_escalations_tl
Definition: pbx_functions.c:46
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.

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

Referenced by ast_add_extension2_lockopt(), and handle_tcptls_connection().

◆ 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.

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}

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

Referenced by ast_add_extension2_lockopt().

◆ complete_functions()

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

Definition at line 105 of file pbx_functions.c.

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}
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
short word

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

Referenced by handle_show_function().

◆ 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.

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

References args, ast_log, and LOG_WARNING.

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

◆ 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.

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], desctitle[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(desctitle, "[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) {
213 ast_free(description);
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, desctitle, description,
229 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
230
233 ast_free(description);
236
237 return CLI_SUCCESS;
238}
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
def info(msg)
#define AST_MAX_APP
Definition: pbx.h:40
static char * complete_functions(const char *word, int pos, int state)
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
const ast_string_field seealso
Definition: pbx.h:126
const ast_string_field syntax
Definition: pbx.h:126
const ast_string_field arguments
Definition: pbx.h:126
#define COLOR_CYAN
Definition: term.h:62
#define COLOR_MAGENTA
Definition: term.h:60
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:235
#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:75
static struct test_val a
char * ast_xmldoc_printable(const char *bwinput, int withcolors)
Colorize and put delimiters (instead of tags) to the xmldoc output.
Definition: xmldoc.c:241

References a, ast_custom_function::arguments, 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, sip_to_pjsip::info(), ast_custom_function::name, NULL, S_OR, ast_custom_function::seealso, synopsis, ast_custom_function::synopsis, ast_custom_function::syntax, term_color(), and ast_cli_entry::usage.

◆ 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.

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}

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

◆ 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.

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}
#define ast_debug(level,...)
Log a DEBUG message.
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.
static int live_dangerously
Set to true (non-zero) to globally allow all dangerous dialplan functions to run.
Definition: pbx_functions.c:52

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

Referenced by ast_func_read(), and ast_func_read2().

◆ 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.

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}
static int write_escalates(const struct ast_custom_function *acf)
Returns true if given custom function escalates privileges on write.

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

Referenced by ast_func_write().

◆ load_pbx_functions_cli()

int load_pbx_functions_cli ( void  )

Provided by pbx_functions.c

Definition at line 733 of file pbx_functions.c.

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

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

Referenced by asterisk_daemon().

◆ 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.

467{
468 if (new_live_dangerously && !live_dangerously) {
469 ast_log(LOG_WARNING, "Privilege escalation protection disabled!\n"
470 "See https://docs.asterisk.org/Configuration/Dialplan/Privilege-Escalations-with-Dialplan-Functions/ 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}
#define LOG_NOTICE

References ast_log, live_dangerously, LOG_NOTICE, and LOG_WARNING.

Referenced by load_asterisk_conf().

◆ 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.

304{
305 return acf->read_escalates;
306}

References ast_custom_function::read_escalates.

Referenced by is_read_allowed().

◆ 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.

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}

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

Referenced by is_read_allowed(), and is_write_allowed().

◆ unload_pbx_functions_cli()

static void unload_pbx_functions_cli ( void  )
static

Definition at line 728 of file pbx_functions.c.

729{
731}
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30

References acf_cli, ARRAY_LEN, and ast_cli_unregister_multiple().

Referenced by load_pbx_functions_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.

316{
317 return acf->write_escalates;
318}

References ast_custom_function::write_escalates.

Referenced by is_write_allowed().

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_functions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pbx_functions.c:61
static char * handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)

Definition at line 723 of file pbx_functions.c.

Referenced by load_pbx_functions_cli(), and unload_pbx_functions_cli().

◆ 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 52 of file pbx_functions.c.

Referenced by is_read_allowed(), is_write_allowed(), 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