Asterisk - The Open Source Telephony Project GIT-master-a358458
pbx_functions.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2015, CFWare, LLC
5 *
6 * Corey Farrell <git@cfware.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*! \file
20 *
21 * \brief Custom function management routines.
22 *
23 * \author Corey Farrell <git@cfware.com>
24 */
25
26/*** MODULEINFO
27 <support_level>core</support_level>
28 ***/
29
30#include "asterisk.h"
31
32#include "asterisk/_private.h"
33#include "asterisk/cli.h"
35#include "asterisk/module.h"
36#include "asterisk/pbx.h"
37#include "asterisk/term.h"
39#include "asterisk/xmldoc.h"
40#include "pbx_private.h"
41
42/*!
43 * \brief A thread local indicating whether the current thread can run
44 * 'dangerous' dialplan functions.
45 */
47
48/*!
49 * \brief Set to true (non-zero) to globally allow all dangerous dialplan
50 * functions to run.
51 */
53
54/*!
55 * \brief Registered functions container.
56 *
57 * It is sorted by function name.
58 */
60
61static char *handle_show_functions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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}
104
105static char *complete_functions(const char *word, int pos, int state)
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}
142
143static char *handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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}
239
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}
261
263{
264 struct ast_custom_function *acf;
265
269
270 return acf;
271}
272
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}
295
296/*!
297 * \brief Returns true if given custom function escalates privileges on read.
298 *
299 * \param acf Custom function to query.
300 * \return True (non-zero) if reads escalate privileges.
301 * \return False (zero) if reads just read.
302 */
303static int read_escalates(const struct ast_custom_function *acf)
304{
305 return acf->read_escalates;
306}
307
308/*!
309 * \brief Returns true if given custom function escalates privileges on write.
310 *
311 * \param acf Custom function to query.
312 * \return True (non-zero) if writes escalate privileges.
313 * \return False (zero) if writes just write.
314 */
315static int write_escalates(const struct ast_custom_function *acf)
316{
317 return acf->write_escalates;
318}
319
320/*! \internal
321 * \brief Retrieve the XML documentation of a specified ast_custom_function,
322 * and populate ast_custom_function string fields.
323 * \param acf ast_custom_function structure with empty 'desc' and 'synopsis'
324 * but with a function 'name'.
325 * \retval -1 On error.
326 * \retval 0 On succes.
327 */
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}
372
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}
417
419{
420 int res;
421
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}
444
445/*! \brief return a pointer to the arguments of the function,
446 * and terminates the function name with '\\0'
447 */
448static char *func_args(char *function)
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}
465
466void pbx_live_dangerously(int new_live_dangerously)
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}
478
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}
493
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}
510
511/*!
512 * \brief Indicates whether the current thread inhibits the execution of
513 * dangerous functions.
514 *
515 * \return True (non-zero) if dangerous function execution is inhibited.
516 * \return False (zero) if dangerous function execution is allowed.
517 */
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}
532
533/*!
534 * \brief Determines whether execution of a custom function's read function
535 * is allowed.
536 *
537 * \param acfptr Custom function to check
538 * \return True (non-zero) if reading is allowed.
539 * \return False (zero) if reading is not allowed.
540 */
541static int is_read_allowed(struct ast_custom_function *acfptr)
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}
565
566/*!
567 * \brief Determines whether execution of a custom function's write function
568 * is allowed.
569 *
570 * \param acfptr Custom function to check
571 * \return True (non-zero) if writing is allowed.
572 * \return False (zero) if writing is not allowed.
573 */
574static int is_write_allowed(struct ast_custom_function *acfptr)
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}
598
599int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
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}
641
642int ast_func_read2(struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen)
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}
692
693int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
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}
722
723static struct ast_cli_entry acf_cli[] = {
724 AST_CLI_DEFINE(handle_show_functions, "Shows registered dialplan functions"),
725 AST_CLI_DEFINE(handle_show_function, "Describe a specific dialplan function"),
726};
727
729{
731}
732
734{
737
738 return 0;
739}
Prototypes for public functions only of internal interest,.
const char * str
Definition: app_jack.c:147
static int copy(char *infile, char *outfile)
Utility function to copy a file.
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define ast_log
Definition: astobj2.c:42
static int maxsize
static const char desc[]
Definition: cdr_radius.c:84
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
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
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
short word
static const char name[]
Definition: format_mp3.c:68
static char * synopsis
Definition: func_enum.c:154
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define ast_verb(level,...)
#define LOG_NOTICE
#define LOG_WARNING
A set of macros to manage forward-linked lists.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
#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_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized.
Definition: linkedlists.h:333
#define AST_RWLIST_REMOVE
Definition: linkedlists.h:885
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:617
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:494
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:741
#define AST_RWLIST_INSERT_BEFORE_CURRENT
Definition: linkedlists.h:610
Asterisk module definitions.
struct ast_module_user * __ast_module_user_add(struct ast_module *, struct ast_channel *)
Definition: loader.c:800
const char * ast_module_name(const struct ast_module *mod)
Get the name of a module.
Definition: loader.c:615
void __ast_module_user_remove(struct ast_module *, struct ast_module_user *)
Definition: loader.c:826
def info(msg)
Core PBX routines and definitions.
#define AST_MAX_APP
Definition: pbx.h:40
ast_custom_function_escalation
Description of the ways in which a function may escalate privileges.
Definition: pbx.h:1548
@ 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
static int thread_inhibits_escalations(void)
Indicates whether the current thread inhibits the execution of dangerous functions.
static int is_read_allowed(struct ast_custom_function *acfptr)
Determines whether execution of a custom function's read function is allowed.
static int read_escalates(const struct ast_custom_function *acf)
Returns true if given custom function escalates privileges on read.
void pbx_live_dangerously(int new_live_dangerously)
Enable/disable the execution of 'dangerous' functions from external protocols (AMI,...
int ast_thread_inhibit_escalations_swap(int inhibit)
Swap the current thread escalation inhibit setting.
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.
static struct ast_custom_function * ast_custom_function_find_nolock(const char *name)
static int write_escalates(const struct ast_custom_function *acf)
Returns true if given custom function escalates privileges on write.
static struct ast_threadstorage thread_inhibit_escalations_tl
Definition: pbx_functions.c:46
struct ast_custom_function * ast_custom_function_find(const char *name)
int load_pbx_functions_cli(void)
static int acf_retrieve_docs(struct ast_custom_function *acf)
static void unload_pbx_functions_cli(void)
static int live_dangerously
Set to true (non-zero) to globally allow all dangerous dialplan functions to run.
Definition: pbx_functions.c:52
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
static char * complete_functions(const char *word, int pos, int state)
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
static char * handle_show_functions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pbx_functions.c:61
int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
executes a read operation on a function
static char * handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
int __ast_custom_function_register(struct ast_custom_function *acf, struct ast_module *mod)
Register a custom function.
static int is_write_allowed(struct ast_custom_function *acfptr)
Determines whether execution of a custom function's write function is allowed.
static char * func_args(char *function)
return a pointer to the arguments of the function, and terminates the function name with '\0'
int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
executes a write operation on a function
int ast_thread_inhibit_escalations(void)
Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations...
static struct ast_cli_entry acf_cli[]
Private include file for pbx.
#define VAR_BUF_SIZE
Definition: pbx_private.h:68
#define NULL
Definition: resample.c:96
#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
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#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
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
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_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
#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
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
Registered functions container.
Definition: pbx_functions.c:59
Main Channel structure associated with a channel.
descriptor for a cli entry.
Definition: cli.h:171
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
ast_acf_write_fn_t write
Definition: pbx.h:141
const ast_string_field desc
Definition: pbx.h:126
ast_acf_read_fn_t read
Definition: pbx.h:129
struct ast_module * mod
Definition: pbx.h:142
const ast_string_field synopsis
Definition: pbx.h:126
enum ast_doc_src docsrc
Definition: pbx.h:127
const ast_string_field seealso
Definition: pbx.h:126
size_t read_max
Definition: pbx.h:139
const ast_string_field syntax
Definition: pbx.h:126
ast_acf_read2_fn_t read2
Definition: pbx.h:137
const ast_string_field arguments
Definition: pbx.h:126
unsigned int read_escalates
Definition: pbx.h:143
unsigned int write_escalates
Definition: pbx.h:147
const char * name
Definition: pbx.h:119
struct ast_channel * chan
Definition: loader.c:128
Support for dynamic strings.
Definition: strings.h:623
int value
Definition: syslog.c:37
Handy terminal functions for vt* terms.
#define COLOR_BRCYAN
Definition: term.h:63
#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
#define COLORIZE(fg, bg, str)
Definition: term.h:72
#define COLORIZE_FMT
Shortcut macros for coloring a set of text.
Definition: term.h:71
const char * args
static struct test_val a
Definitions to aid in the use of thread local storage.
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
Definition: threadstorage.h:86
#define ARRAY_LEN(a)
Definition: utils.h:666
Asterisk XML Documentation API.
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
@ AST_STATIC_DOC
Definition: xmldoc.h:32
char * ast_xmldoc_build_seealso(const char *type, const char *name, const char *module)
Parse the <see-also> node content.
Definition: xmldoc.c:1702
char * ast_xmldoc_printable(const char *bwinput, int withcolors)
Colorize and put delimiters (instead of tags) to the xmldoc output.
Definition: xmldoc.c:241