Asterisk - The Open Source Telephony Project GIT-master-80b953f
Loading...
Searching...
No Matches
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 */
46AST_THREADSTORAGE(thread_inhibit_escalations_tl);
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
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);
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, *provided_by = 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 provided_by = ast_xmldoc_printable(S_OR(acf->provided_by, "Not available"), 1);
175 since = ast_xmldoc_printable(S_OR(acf->since, "Not available"), 1);
176 description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1);
177 syntax = ast_xmldoc_printable(S_OR(acf->syntax, "Not available"), 1);
178 arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1);
179 seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1);
180 } else
181#endif
182 {
183 synopsis = ast_strdup(S_OR(acf->synopsis, "Not Available"));
184 provided_by = ast_strdup(S_OR(acf->provided_by, "Not available"));
185 since = ast_strdup(S_OR(acf->since, "Not Available"));
186 description = ast_strdup(S_OR(acf->desc, "Not Available"));
187 syntax = ast_strdup(S_OR(acf->syntax, "Not Available"));
188 arguments = ast_strdup(S_OR(acf->arguments, "Not Available"));
189 seealso = ast_strdup(S_OR(acf->seealso, "Not Available"));
190 }
191 /* check allocated memory. */
192 if (!synopsis || !provided_by || !since || !description || !syntax || !arguments || !seealso) {
193 rtn = CLI_FAILURE;
194 goto free_docs;
195 }
196
197 ast_cli(a->fd, "\n"
198 "%s -= Info about Function '%s' =- %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"
209 COLORIZE_FMT "\n"
210 "%s\n\n"
211 COLORIZE_FMT "\n"
212 "%s\n\n",
214 COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis,
215 COLORIZE(COLOR_MAGENTA, 0, "[Provided By]"), provided_by,
216 COLORIZE(COLOR_MAGENTA, 0, "[Since]"), since,
217 COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description,
218 COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), syntax,
219 COLORIZE(COLOR_MAGENTA, 0, "[Arguments]"), arguments,
220 COLORIZE(COLOR_MAGENTA, 0, "[See Also]"), seealso
221 );
222
223free_docs:
225 ast_free(provided_by);
226 ast_free(since);
227 ast_free(description);
231
232 return rtn;
233}
234
236{
237 struct ast_custom_function *cur;
238 int cmp;
239
241 cmp = strcmp(name, cur->name);
242 if (cmp > 0) {
243 continue;
244 }
245 if (!cmp) {
246 /* Found it. */
247 break;
248 }
249 /* Not in container. */
250 cur = NULL;
251 break;
252 }
253
254 return cur;
255}
256
258{
259 struct ast_custom_function *acf;
260
264
265 return acf;
266}
267
269{
270 struct ast_custom_function *cur;
271
272 if (!acf) {
273 return -1;
274 }
275
277 cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist);
278 if (cur) {
279#ifdef AST_XML_DOCS
280 if (cur->docsrc == AST_XML_DOC) {
282 }
283#endif
284 ast_verb(5, "Unregistered custom function %s\n", cur->name);
285 }
287
288 return cur ? 0 : -1;
289}
290
291/*!
292 * \brief Returns true if given custom function escalates privileges on read.
293 *
294 * \param acf Custom function to query.
295 * \return True (non-zero) if reads escalate privileges.
296 * \return False (zero) if reads just read.
297 */
298static int read_escalates(const struct ast_custom_function *acf)
299{
300 return acf->read_escalates;
301}
302
303/*!
304 * \brief Returns true if given custom function escalates privileges on write.
305 *
306 * \param acf Custom function to query.
307 * \return True (non-zero) if writes escalate privileges.
308 * \return False (zero) if writes just write.
309 */
310static int write_escalates(const struct ast_custom_function *acf)
311{
312 return acf->write_escalates;
313}
314
315/*! \internal
316 * \brief Retrieve the XML documentation of a specified ast_custom_function,
317 * and populate ast_custom_function string fields.
318 * \param acf ast_custom_function structure with empty 'desc' and 'synopsis'
319 * but with a function 'name'.
320 * \retval -1 On error.
321 * \retval 0 On success.
322 */
324{
325#ifdef AST_XML_DOCS
326 char *tmpxml;
327
328 /* Let's try to find it in the Documentation XML */
329 if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) {
330 return 0;
331 }
332
333 if (ast_string_field_init(acf, 128)) {
334 return -1;
335 }
336
337 if (ast_string_field_init_extended(acf, since)) {
339 return -1;
340 }
341
342 if (ast_string_field_init_extended(acf, provided_by)) {
344 return -1;
345 }
346
347 /* load synopsis */
348 tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod));
349 ast_string_field_set(acf, synopsis, tmpxml);
350 ast_free(tmpxml);
351
352 /* load provided_by */
353 tmpxml = ast_xmldoc_build_provided_by("function", acf->name, ast_module_name(acf->mod));
354 ast_string_field_set(acf, provided_by, tmpxml);
355 ast_free(tmpxml);
356
357 /* load since */
358 tmpxml = ast_xmldoc_build_since("function", acf->name, ast_module_name(acf->mod));
359 ast_string_field_set(acf, since, tmpxml);
360 ast_free(tmpxml);
361
362 /* load description */
363 tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod));
364 ast_string_field_set(acf, desc, tmpxml);
365 ast_free(tmpxml);
366
367 /* load syntax */
368 tmpxml = ast_xmldoc_build_syntax("function", acf->name, ast_module_name(acf->mod));
369 ast_string_field_set(acf, syntax, tmpxml);
370 ast_free(tmpxml);
371
372 /* load arguments */
373 tmpxml = ast_xmldoc_build_arguments("function", acf->name, ast_module_name(acf->mod));
374 ast_string_field_set(acf, arguments, tmpxml);
375 ast_free(tmpxml);
376
377 /* load seealso */
378 tmpxml = ast_xmldoc_build_seealso("function", acf->name, ast_module_name(acf->mod));
379 ast_string_field_set(acf, seealso, tmpxml);
380 ast_free(tmpxml);
381
382 acf->docsrc = AST_XML_DOC;
383#endif
384
385 return 0;
386}
387
389{
390 struct ast_custom_function *cur;
391
392 if (!acf) {
393 return -1;
394 }
395
396 acf->mod = mod;
397#ifdef AST_XML_DOCS
398 acf->docsrc = AST_STATIC_DOC;
399#endif
400
401 if (acf_retrieve_docs(acf)) {
402 return -1;
403 }
404
406
408 if (cur) {
409 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
411 return -1;
412 }
413
414 /* Store in alphabetical order */
416 if (strcmp(acf->name, cur->name) < 0) {
418 break;
419 }
420 }
422 if (!cur) {
424 }
425
427
428 ast_verb(5, "Registered custom function '" COLORIZE_FMT "'\n", COLORIZE(COLOR_BRCYAN, 0, acf->name));
429
430 return 0;
431}
432
434{
435 int res;
436
438 if (res != 0) {
439 return -1;
440 }
441
442 switch (escalation) {
443 case AST_CFE_NONE:
444 break;
445 case AST_CFE_READ:
446 acf->read_escalates = 1;
447 break;
448 case AST_CFE_WRITE:
449 acf->write_escalates = 1;
450 break;
451 case AST_CFE_BOTH:
452 acf->read_escalates = 1;
453 acf->write_escalates = 1;
454 break;
455 }
456
457 return 0;
458}
459
460/*! \brief return a pointer to the arguments of the function,
461 * and terminates the function name with '\\0'
462 */
463static char *func_args(char *function)
464{
465 char *args = strchr(function, '(');
466
467 if (!args) {
468 ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses. Assuming null argument.\n", function);
469 } else {
470 char *p;
471 *args++ = '\0';
472 if ((p = strrchr(args, ')'))) {
473 *p = '\0';
474 } else {
475 ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args);
476 }
477 }
478 return args;
479}
480
481void pbx_live_dangerously(int new_live_dangerously)
482{
483 if (new_live_dangerously && !live_dangerously) {
484 ast_log(LOG_WARNING, "Privilege escalation protection disabled!\n"
485 "See https://docs.asterisk.org/Configuration/Dialplan/Privilege-Escalations-with-Dialplan-Functions/ for more details.\n");
486 }
487
488 if (!new_live_dangerously && live_dangerously) {
489 ast_log(LOG_NOTICE, "Privilege escalation protection enabled.\n");
490 }
491 live_dangerously = new_live_dangerously;
492}
493
495{
496 int *thread_inhibit_escalations;
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 inhibiting privilege escalations for current thread\n");
502 return -1;
503 }
504
505 *thread_inhibit_escalations = 1;
506 return 0;
507}
508
510{
511 int *thread_inhibit_escalations;
512 int orig;
513
514 thread_inhibit_escalations = ast_threadstorage_get(
515 &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
516 if (thread_inhibit_escalations == NULL) {
517 ast_log(LOG_ERROR, "Error swapping privilege escalations inhibit for current thread\n");
518 return -1;
519 }
520
521 orig = *thread_inhibit_escalations;
522 *thread_inhibit_escalations = !!inhibit;
523 return orig;
524}
525
526/*!
527 * \brief Indicates whether the current thread inhibits the execution of
528 * dangerous functions.
529 *
530 * \return True (non-zero) if dangerous function execution is inhibited.
531 * \return False (zero) if dangerous function execution is allowed.
532 */
534{
535 int *thread_inhibit_escalations;
536
537 thread_inhibit_escalations = ast_threadstorage_get(
538 &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
539 if (thread_inhibit_escalations == NULL) {
540 ast_log(LOG_ERROR, "Error checking thread's ability to run dangerous functions\n");
541 /* On error, assume that we are inhibiting */
542 return 1;
543 }
544
545 return *thread_inhibit_escalations;
546}
547
548/*!
549 * \brief Determines whether execution of a custom function's read function
550 * is allowed.
551 *
552 * \param acfptr Custom function to check
553 * \return True (non-zero) if reading is allowed.
554 * \return False (zero) if reading is not allowed.
555 */
556static int is_read_allowed(struct ast_custom_function *acfptr)
557{
558 if (!acfptr) {
559 return 1;
560 }
561
562 if (!read_escalates(acfptr)) {
563 return 1;
564 }
565
567 return 1;
568 }
569
570 if (live_dangerously) {
571 /* Global setting overrides the thread's preference */
572 ast_debug(2, "Reading %s from a dangerous context\n",
573 acfptr->name);
574 return 1;
575 }
576
577 /* We have no reason to allow this function to execute */
578 return 0;
579}
580
581/*!
582 * \brief Determines whether execution of a custom function's write function
583 * is allowed.
584 *
585 * \param acfptr Custom function to check
586 * \return True (non-zero) if writing is allowed.
587 * \return False (zero) if writing is not allowed.
588 */
589static int is_write_allowed(struct ast_custom_function *acfptr)
590{
591 if (!acfptr) {
592 return 1;
593 }
594
595 if (!write_escalates(acfptr)) {
596 return 1;
597 }
598
600 return 1;
601 }
602
603 if (live_dangerously) {
604 /* Global setting overrides the thread's preference */
605 ast_debug(2, "Writing %s from a dangerous context\n",
606 acfptr->name);
607 return 1;
608 }
609
610 /* We have no reason to allow this function to execute */
611 return 0;
612}
613
614int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
615{
616 char *copy = ast_strdupa(function);
617 char *args = func_args(copy);
619 int res;
620 struct ast_module_user *u = NULL;
621
622 if (acfptr == NULL) {
623 ast_log(LOG_ERROR, "Function %s not registered\n", copy);
624 } else if (!acfptr->read && !acfptr->read2) {
625 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
626 } else if (!is_read_allowed(acfptr)) {
627 ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy);
628 } else if (acfptr->read) {
629 if (acfptr->mod) {
630 u = __ast_module_user_add(acfptr->mod, chan);
631 }
632 res = acfptr->read(chan, copy, args, workspace, len);
633 if (acfptr->mod && u) {
634 __ast_module_user_remove(acfptr->mod, u);
635 }
636
637 return res;
638 } else {
639 struct ast_str *str = ast_str_create(16);
640
641 if (acfptr->mod) {
642 u = __ast_module_user_add(acfptr->mod, chan);
643 }
644 res = acfptr->read2(chan, copy, args, &str, 0);
645 if (acfptr->mod && u) {
646 __ast_module_user_remove(acfptr->mod, u);
647 }
649 ast_free(str);
650
651 return res;
652 }
653
654 return -1;
655}
656
657int ast_func_read2(struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen)
658{
659 char *copy = ast_strdupa(function);
660 char *args = func_args(copy);
662 int res;
663 struct ast_module_user *u = NULL;
664
665 if (acfptr == NULL) {
666 ast_log(LOG_ERROR, "Function %s not registered\n", copy);
667 } else if (!acfptr->read && !acfptr->read2) {
668 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
669 } else if (!is_read_allowed(acfptr)) {
670 ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy);
671 } else {
672 if (acfptr->mod) {
673 u = __ast_module_user_add(acfptr->mod, chan);
674 }
676 if (acfptr->read2) {
677 /* ast_str enabled */
678 res = acfptr->read2(chan, copy, args, str, maxlen);
679 } else {
680 /* Legacy function pointer, allocate buffer for result */
681 int maxsize = ast_str_size(*str);
682
683 if (maxlen > -1) {
684 if (maxlen == 0) {
685 if (acfptr->read_max) {
686 maxsize = acfptr->read_max;
687 } else {
689 }
690 } else {
691 maxsize = maxlen;
692 }
694 }
695 res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
696 ast_str_update(*str); /* Manually set the string length */
697 }
698 if (acfptr->mod && u) {
699 __ast_module_user_remove(acfptr->mod, u);
700 }
701
702 return res;
703 }
704
705 return -1;
706}
707
708int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
709{
710 char *copy = ast_strdupa(function);
711 char *args = func_args(copy);
713
714 if (acfptr == NULL) {
715 ast_log(LOG_ERROR, "Function %s not registered\n", copy);
716 } else if (!acfptr->write) {
717 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
718 } else if (!is_write_allowed(acfptr)) {
719 ast_log(LOG_ERROR, "Dangerous function %s write blocked\n", copy);
720 } else {
721 int res;
722 struct ast_module_user *u = NULL;
723
724 if (acfptr->mod) {
725 u = __ast_module_user_add(acfptr->mod, chan);
726 }
727 res = acfptr->write(chan, copy, args, value);
728 if (acfptr->mod && u) {
729 __ast_module_user_remove(acfptr->mod, u);
730 }
731
732 return res;
733 }
734
735 return -1;
736}
737
738static struct ast_cli_entry acf_cli[] = {
739 AST_CLI_DEFINE(handle_show_functions, "Shows registered dialplan functions"),
740 AST_CLI_DEFINE(handle_show_function, "Describe a specific dialplan function"),
741};
742
747
Prototypes for public functions only of internal interest,.
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408
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
#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
#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.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized.
#define AST_RWLIST_REMOVE
#define AST_RWLIST_TRAVERSE_SAFE_END
#define AST_RWLIST_TRAVERSE
#define AST_RWLIST_INSERT_TAIL
#define AST_RWLIST_INSERT_BEFORE_CURRENT
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:1553
@ AST_CFE_NONE
Definition pbx.h:1554
@ AST_CFE_READ
Definition pbx.h:1555
@ AST_CFE_WRITE
Definition pbx.h:1556
@ AST_CFE_BOTH
Definition pbx.h:1557
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.
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.
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)
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
static struct @521 args
#define NULL
Definition resample.c:96
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_string_field_init_extended(x, field)
Initialize an extended string field.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
#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
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition strings.h:761
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425
size_t attribute_pure 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.
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
struct ast_custom_function::@252 acflist
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
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.
#define ARRAY_LEN(a)
Definition utils.h:706
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:2418
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:2231
char * ast_xmldoc_build_synopsis(const char *type, const char *name, const char *module)
Generate synopsis documentation from XML.
Definition xmldoc.c:2395
char * ast_xmldoc_build_since(const char *type, const char *name, const char *module)
Parse the <since> node content.
Definition xmldoc.c:1792
@ 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:1707
char * ast_xmldoc_build_provided_by(const char *type, const char *name, const char *module)
Generate provided-by documentation from XML.
Definition xmldoc.c:1844
char * ast_xmldoc_printable(const char *bwinput, int withcolors)
Colorize and put delimiters (instead of tags) to the xmldoc output.
Definition xmldoc.c:241