Asterisk - The Open Source Telephony Project GIT-master-8924258
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 *synopsis = NULL, *since = NULL, *description = NULL, *syntax = NULL, *arguments = NULL, *seealso = NULL;
148 char *rtn = CLI_SUCCESS;
149
150 switch (cmd) {
151 case CLI_INIT:
152 e->command = "core show function";
153 e->usage =
154 "Usage: core show function <function>\n"
155 " Describe a particular dialplan function.\n";
156 return NULL;
157 case CLI_GENERATE:
158 return complete_functions(a->word, a->pos, a->n);
159 }
160
161 if (a->argc != 4) {
162 return CLI_SHOWUSAGE;
163 }
164
165 if (!(acf = ast_custom_function_find(a->argv[3]))) {
166 ast_cli(a->fd, "No function by that name registered.\n");
167
168 return CLI_FAILURE;
169 }
170
171#ifdef AST_XML_DOCS
172 if (acf->docsrc == AST_XML_DOC) {
173 synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1);
174 since = ast_xmldoc_printable(S_OR(acf->since, "Not available"), 1);
175 description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1);
176 syntax = ast_xmldoc_printable(S_OR(acf->syntax, "Not available"), 1);
177 arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1);
178 seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1);
179 } else
180#endif
181 {
182 synopsis = ast_strdup(S_OR(acf->synopsis, "Not Available"));
183 since = ast_strdup(S_OR(acf->since, "Not Available"));
184 description = ast_strdup(S_OR(acf->desc, "Not Available"));
185 syntax = ast_strdup(S_OR(acf->syntax, "Not Available"));
186 arguments = ast_strdup(S_OR(acf->arguments, "Not Available"));
187 seealso = ast_strdup(S_OR(acf->seealso, "Not Available"));
188 }
189 /* check allocated memory. */
190 if (!synopsis || !since || !description || !syntax || !arguments || !seealso) {
191 rtn = CLI_FAILURE;
192 goto free_docs;
193 }
194
195 ast_cli(a->fd, "\n"
196 "%s -= Info about Function '%s' =- %s\n\n"
197 COLORIZE_FMT "\n"
198 "%s\n\n"
199 COLORIZE_FMT "\n"
200 "%s\n\n"
201 COLORIZE_FMT "\n"
202 "%s\n\n"
203 COLORIZE_FMT "\n"
204 "%s\n\n"
205 COLORIZE_FMT "\n"
206 "%s\n\n"
207 COLORIZE_FMT "\n"
208 "%s\n\n",
210 COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis,
211 COLORIZE(COLOR_MAGENTA, 0, "[Since]"), since,
212 COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description,
213 COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), syntax,
214 COLORIZE(COLOR_MAGENTA, 0, "[Arguments]"), arguments,
215 COLORIZE(COLOR_MAGENTA, 0, "[See Also]"), seealso
216 );
217
218free_docs:
220 ast_free(since);
221 ast_free(description);
225
226 return rtn;
227}
228
230{
231 struct ast_custom_function *cur;
232 int cmp;
233
234 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
235 cmp = strcmp(name, cur->name);
236 if (cmp > 0) {
237 continue;
238 }
239 if (!cmp) {
240 /* Found it. */
241 break;
242 }
243 /* Not in container. */
244 cur = NULL;
245 break;
246 }
247
248 return cur;
249}
250
252{
253 struct ast_custom_function *acf;
254
258
259 return acf;
260}
261
263{
264 struct ast_custom_function *cur;
265
266 if (!acf) {
267 return -1;
268 }
269
271 cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist);
272 if (cur) {
273#ifdef AST_XML_DOCS
274 if (cur->docsrc == AST_XML_DOC) {
276 }
277#endif
278 ast_verb(5, "Unregistered custom function %s\n", cur->name);
279 }
281
282 return cur ? 0 : -1;
283}
284
285/*!
286 * \brief Returns true if given custom function escalates privileges on read.
287 *
288 * \param acf Custom function to query.
289 * \return True (non-zero) if reads escalate privileges.
290 * \return False (zero) if reads just read.
291 */
292static int read_escalates(const struct ast_custom_function *acf)
293{
294 return acf->read_escalates;
295}
296
297/*!
298 * \brief Returns true if given custom function escalates privileges on write.
299 *
300 * \param acf Custom function to query.
301 * \return True (non-zero) if writes escalate privileges.
302 * \return False (zero) if writes just write.
303 */
304static int write_escalates(const struct ast_custom_function *acf)
305{
306 return acf->write_escalates;
307}
308
309/*! \internal
310 * \brief Retrieve the XML documentation of a specified ast_custom_function,
311 * and populate ast_custom_function string fields.
312 * \param acf ast_custom_function structure with empty 'desc' and 'synopsis'
313 * but with a function 'name'.
314 * \retval -1 On error.
315 * \retval 0 On success.
316 */
318{
319#ifdef AST_XML_DOCS
320 char *tmpxml;
321
322 /* Let's try to find it in the Documentation XML */
323 if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) {
324 return 0;
325 }
326
327 if (ast_string_field_init(acf, 128)) {
328 return -1;
329 }
330
331 if (ast_string_field_init_extended(acf, since)) {
333 return -1;
334 }
335
336 /* load synopsis */
337 tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod));
338 ast_string_field_set(acf, synopsis, tmpxml);
339 ast_free(tmpxml);
340
341 /* load since */
342 tmpxml = ast_xmldoc_build_since("function", acf->name, ast_module_name(acf->mod));
343 ast_string_field_set(acf, since, tmpxml);
344 ast_free(tmpxml);
345
346 /* load description */
347 tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod));
348 ast_string_field_set(acf, desc, tmpxml);
349 ast_free(tmpxml);
350
351 /* load syntax */
352 tmpxml = ast_xmldoc_build_syntax("function", acf->name, ast_module_name(acf->mod));
353 ast_string_field_set(acf, syntax, tmpxml);
354 ast_free(tmpxml);
355
356 /* load arguments */
357 tmpxml = ast_xmldoc_build_arguments("function", acf->name, ast_module_name(acf->mod));
358 ast_string_field_set(acf, arguments, tmpxml);
359 ast_free(tmpxml);
360
361 /* load seealso */
362 tmpxml = ast_xmldoc_build_seealso("function", acf->name, ast_module_name(acf->mod));
363 ast_string_field_set(acf, seealso, tmpxml);
364 ast_free(tmpxml);
365
366 acf->docsrc = AST_XML_DOC;
367#endif
368
369 return 0;
370}
371
373{
374 struct ast_custom_function *cur;
375
376 if (!acf) {
377 return -1;
378 }
379
380 acf->mod = mod;
381#ifdef AST_XML_DOCS
382 acf->docsrc = AST_STATIC_DOC;
383#endif
384
385 if (acf_retrieve_docs(acf)) {
386 return -1;
387 }
388
390
392 if (cur) {
393 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
395 return -1;
396 }
397
398 /* Store in alphabetical order */
400 if (strcmp(acf->name, cur->name) < 0) {
402 break;
403 }
404 }
406 if (!cur) {
407 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
408 }
409
411
412 ast_verb(5, "Registered custom function '" COLORIZE_FMT "'\n", COLORIZE(COLOR_BRCYAN, 0, acf->name));
413
414 return 0;
415}
416
418{
419 int res;
420
422 if (res != 0) {
423 return -1;
424 }
425
426 switch (escalation) {
427 case AST_CFE_NONE:
428 break;
429 case AST_CFE_READ:
430 acf->read_escalates = 1;
431 break;
432 case AST_CFE_WRITE:
433 acf->write_escalates = 1;
434 break;
435 case AST_CFE_BOTH:
436 acf->read_escalates = 1;
437 acf->write_escalates = 1;
438 break;
439 }
440
441 return 0;
442}
443
444/*! \brief return a pointer to the arguments of the function,
445 * and terminates the function name with '\\0'
446 */
447static char *func_args(char *function)
448{
449 char *args = strchr(function, '(');
450
451 if (!args) {
452 ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses. Assuming null argument.\n", function);
453 } else {
454 char *p;
455 *args++ = '\0';
456 if ((p = strrchr(args, ')'))) {
457 *p = '\0';
458 } else {
459 ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args);
460 }
461 }
462 return args;
463}
464
465void pbx_live_dangerously(int new_live_dangerously)
466{
467 if (new_live_dangerously && !live_dangerously) {
468 ast_log(LOG_WARNING, "Privilege escalation protection disabled!\n"
469 "See https://docs.asterisk.org/Configuration/Dialplan/Privilege-Escalations-with-Dialplan-Functions/ for more details.\n");
470 }
471
472 if (!new_live_dangerously && live_dangerously) {
473 ast_log(LOG_NOTICE, "Privilege escalation protection enabled.\n");
474 }
475 live_dangerously = new_live_dangerously;
476}
477
479{
480 int *thread_inhibit_escalations;
481
482 thread_inhibit_escalations = ast_threadstorage_get(
483 &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
484 if (thread_inhibit_escalations == NULL) {
485 ast_log(LOG_ERROR, "Error inhibiting privilege escalations for current thread\n");
486 return -1;
487 }
488
489 *thread_inhibit_escalations = 1;
490 return 0;
491}
492
494{
495 int *thread_inhibit_escalations;
496 int orig;
497
498 thread_inhibit_escalations = ast_threadstorage_get(
499 &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
500 if (thread_inhibit_escalations == NULL) {
501 ast_log(LOG_ERROR, "Error swapping privilege escalations inhibit for current thread\n");
502 return -1;
503 }
504
505 orig = *thread_inhibit_escalations;
506 *thread_inhibit_escalations = !!inhibit;
507 return orig;
508}
509
510/*!
511 * \brief Indicates whether the current thread inhibits the execution of
512 * dangerous functions.
513 *
514 * \return True (non-zero) if dangerous function execution is inhibited.
515 * \return False (zero) if dangerous function execution is allowed.
516 */
518{
519 int *thread_inhibit_escalations;
520
521 thread_inhibit_escalations = ast_threadstorage_get(
522 &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
523 if (thread_inhibit_escalations == NULL) {
524 ast_log(LOG_ERROR, "Error checking thread's ability to run dangerous functions\n");
525 /* On error, assume that we are inhibiting */
526 return 1;
527 }
528
529 return *thread_inhibit_escalations;
530}
531
532/*!
533 * \brief Determines whether execution of a custom function's read function
534 * is allowed.
535 *
536 * \param acfptr Custom function to check
537 * \return True (non-zero) if reading is allowed.
538 * \return False (zero) if reading is not allowed.
539 */
540static int is_read_allowed(struct ast_custom_function *acfptr)
541{
542 if (!acfptr) {
543 return 1;
544 }
545
546 if (!read_escalates(acfptr)) {
547 return 1;
548 }
549
551 return 1;
552 }
553
554 if (live_dangerously) {
555 /* Global setting overrides the thread's preference */
556 ast_debug(2, "Reading %s from a dangerous context\n",
557 acfptr->name);
558 return 1;
559 }
560
561 /* We have no reason to allow this function to execute */
562 return 0;
563}
564
565/*!
566 * \brief Determines whether execution of a custom function's write function
567 * is allowed.
568 *
569 * \param acfptr Custom function to check
570 * \return True (non-zero) if writing is allowed.
571 * \return False (zero) if writing is not allowed.
572 */
573static int is_write_allowed(struct ast_custom_function *acfptr)
574{
575 if (!acfptr) {
576 return 1;
577 }
578
579 if (!write_escalates(acfptr)) {
580 return 1;
581 }
582
584 return 1;
585 }
586
587 if (live_dangerously) {
588 /* Global setting overrides the thread's preference */
589 ast_debug(2, "Writing %s from a dangerous context\n",
590 acfptr->name);
591 return 1;
592 }
593
594 /* We have no reason to allow this function to execute */
595 return 0;
596}
597
598int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
599{
600 char *copy = ast_strdupa(function);
601 char *args = func_args(copy);
603 int res;
604 struct ast_module_user *u = NULL;
605
606 if (acfptr == NULL) {
607 ast_log(LOG_ERROR, "Function %s not registered\n", copy);
608 } else if (!acfptr->read && !acfptr->read2) {
609 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
610 } else if (!is_read_allowed(acfptr)) {
611 ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy);
612 } else if (acfptr->read) {
613 if (acfptr->mod) {
614 u = __ast_module_user_add(acfptr->mod, chan);
615 }
616 res = acfptr->read(chan, copy, args, workspace, len);
617 if (acfptr->mod && u) {
618 __ast_module_user_remove(acfptr->mod, u);
619 }
620
621 return res;
622 } else {
623 struct ast_str *str = ast_str_create(16);
624
625 if (acfptr->mod) {
626 u = __ast_module_user_add(acfptr->mod, chan);
627 }
628 res = acfptr->read2(chan, copy, args, &str, 0);
629 if (acfptr->mod && u) {
630 __ast_module_user_remove(acfptr->mod, u);
631 }
633 ast_free(str);
634
635 return res;
636 }
637
638 return -1;
639}
640
641int ast_func_read2(struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen)
642{
643 char *copy = ast_strdupa(function);
644 char *args = func_args(copy);
646 int res;
647 struct ast_module_user *u = NULL;
648
649 if (acfptr == NULL) {
650 ast_log(LOG_ERROR, "Function %s not registered\n", copy);
651 } else if (!acfptr->read && !acfptr->read2) {
652 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
653 } else if (!is_read_allowed(acfptr)) {
654 ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy);
655 } else {
656 if (acfptr->mod) {
657 u = __ast_module_user_add(acfptr->mod, chan);
658 }
660 if (acfptr->read2) {
661 /* ast_str enabled */
662 res = acfptr->read2(chan, copy, args, str, maxlen);
663 } else {
664 /* Legacy function pointer, allocate buffer for result */
665 int maxsize = ast_str_size(*str);
666
667 if (maxlen > -1) {
668 if (maxlen == 0) {
669 if (acfptr->read_max) {
670 maxsize = acfptr->read_max;
671 } else {
673 }
674 } else {
675 maxsize = maxlen;
676 }
678 }
679 res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
680 ast_str_update(*str); /* Manually set the string length */
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}
691
692int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
693{
694 char *copy = ast_strdupa(function);
695 char *args = func_args(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}
721
722static struct ast_cli_entry acf_cli[] = {
723 AST_CLI_DEFINE(handle_show_functions, "Shows registered dialplan functions"),
724 AST_CLI_DEFINE(handle_show_function, "Describe a specific dialplan function"),
725};
726
728{
730}
731
733{
736
737 return 0;
738}
Prototypes for public functions only of internal interest,.
const char * str
Definition: app_jack.c:150
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_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:166
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:809
const char * ast_module_name(const struct ast_module *mod)
Get the name of a module.
Definition: loader.c:624
void __ast_module_user_remove(struct ast_module *, struct ast_module_user *)
Definition: loader.c:835
Core PBX routines and definitions.
ast_custom_function_escalation
Description of the ways in which a function may escalate privileges.
Definition: pbx.h:1549
@ AST_CFE_NONE
Definition: pbx.h:1550
@ AST_CFE_READ
Definition: pbx.h:1551
@ AST_CFE_WRITE
Definition: pbx.h:1552
@ AST_CFE_BOTH
Definition: pbx.h:1553
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_init_extended(x, field)
Initialize an extended string field.
Definition: stringfields.h:401
#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:137
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
const char * ast_term_reset(void)
Returns the terminal reset code.
Definition: term.c:357
#define COLOR_MAGENTA
Definition: term.h:60
const char * ast_term_color(int fgcolor, int bgcolor)
Return a color sequence string.
Definition: term.c:341
#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:2356
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:2169
char * ast_xmldoc_build_synopsis(const char *type, const char *name, const char *module)
Generate synopsis documentation from XML.
Definition: xmldoc.c:2333
char * ast_xmldoc_build_since(const char *type, const char *name, const char *module)
Parse the <since> node content.
Definition: xmldoc.c:1787
@ 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