diff options
author | David M. Lee <dlee@digium.com> | 2013-12-16 19:11:51 +0000 |
---|---|---|
committer | David M. Lee <dlee@digium.com> | 2013-12-16 19:11:51 +0000 |
commit | 744556c01d6e28d4ae46c347f77edfb71778d924 (patch) | |
tree | bc90f83b4ec9ef0eafb3d952076bf9ea24406366 /funcs/func_realtime.c | |
parent | 00dcee2a640394ac0aae294396d96985c6c1aba1 (diff) |
security: Inhibit execution of privilege escalating functions
This patch allows individual dialplan functions to be marked as
'dangerous', to inhibit their execution from external sources.
A 'dangerous' function is one which results in a privilege escalation.
For example, if one were to read the channel variable SHELL(rm -rf /)
Bad Things(TM) could happen; even if the external source has only read
permissions.
Execution from external sources may be enabled by setting
'live_dangerously' to 'yes' in the [options] section of asterisk.conf.
Although doing so is not recommended.
Also, the ABI was changed to something more reasonable, since Asterisk
12 does not yet have a public release.
(closes issue ASTERISK-22905)
Review: http://reviewboard.digium.internal/r/432/
........
Merged revisions 403913 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 403917 from http://svn.asterisk.org/svn/asterisk/branches/11
........
Merged revisions 403959 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@403960 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'funcs/func_realtime.c')
-rw-r--r-- | funcs/func_realtime.c | 62 |
1 files changed, 41 insertions, 21 deletions
diff --git a/funcs/func_realtime.c b/funcs/func_realtime.c index 886b5b456..a870ab450 100644 --- a/funcs/func_realtime.c +++ b/funcs/func_realtime.c @@ -115,6 +115,12 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") <description> <para>This function acts in the same way as REALTIME(....) does, except that it destroys the matched record in the RT engine.</para> + <note> + <para>If <literal>live_dangerously</literal> in <literal>asterisk.conf</literal> + is set to <literal>no</literal>, this function can only be read from the + dialplan, and not directly from external protocols. It can, however, be + executed as a write operation (<literal>REALTIME_DESTROY(family, fieldmatch)=ignored</literal>)</para> + </note> </description> <see-also> <ref type="function">REALTIME</ref> @@ -439,28 +445,32 @@ static int function_realtime_readdestroy(struct ast_channel *chan, const char *c return -1; } - resultslen = 0; - n = 0; - for (var = head; var; n++, var = var->next) - resultslen += strlen(var->name) + strlen(var->value); - /* add space for delimiters and final '\0' */ - resultslen += n * (strlen(args.delim1) + strlen(args.delim2)) + 1; - - if (resultslen > len) { - /* Unfortunately this does mean that we cannot destroy the row - * anymore. But OTOH, we're not destroying someones data without - * giving him the chance to look at it. */ - ast_log(LOG_WARNING, "Failed to fetch/destroy. Realtime data is too large: need %zu, have %zu.\n", resultslen, len); - return -1; - } + if (len > 0) { + resultslen = 0; + n = 0; + for (var = head; var; n++, var = var->next) { + resultslen += strlen(var->name) + strlen(var->value); + } + /* add space for delimiters and final '\0' */ + resultslen += n * (strlen(args.delim1) + strlen(args.delim2)) + 1; + + if (resultslen > len) { + /* Unfortunately this does mean that we cannot destroy + * the row anymore. But OTOH, we're not destroying + * someones data without giving him the chance to look + * at it. */ + ast_log(LOG_WARNING, "Failed to fetch/destroy. Realtime data is too large: need %zu, have %zu.\n", resultslen, len); + return -1; + } - /* len is going to be sensible, so we don't need to check for stack - * overflows here. */ - out = ast_str_alloca(resultslen); - for (var = head; var; var = var->next) { - ast_str_append(&out, 0, "%s%s%s%s", var->name, args.delim2, var->value, args.delim1); + /* len is going to be sensible, so we don't need to check for + * stack overflows here. */ + out = ast_str_alloca(resultslen); + for (var = head; var; var = var->next) { + ast_str_append(&out, 0, "%s%s%s%s", var->name, args.delim2, var->value, args.delim1); + } + ast_copy_string(buf, ast_str_buffer(out), len); } - ast_copy_string(buf, ast_str_buffer(out), len); ast_destroy_realtime(args.family, args.fieldmatch, args.value, SENTINEL); ast_variables_destroy(head); @@ -471,6 +481,15 @@ static int function_realtime_readdestroy(struct ast_channel *chan, const char *c return 0; } +/*! + * \brief Wrapper to execute REALTIME_DESTROY from a write operation. Allows + * execution even if live_dangerously is disabled. + */ +static int function_realtime_writedestroy(struct ast_channel *chan, const char *cmd, char *data, const char *value) +{ + return function_realtime_readdestroy(chan, cmd, data, NULL, 0); +} + static struct ast_custom_function realtime_function = { .name = "REALTIME", .read = function_realtime_read, @@ -496,6 +515,7 @@ static struct ast_custom_function realtime_store_function = { static struct ast_custom_function realtime_destroy_function = { .name = "REALTIME_DESTROY", .read = function_realtime_readdestroy, + .write = function_realtime_writedestroy, }; static int unload_module(void) @@ -514,7 +534,7 @@ static int load_module(void) int res = 0; res |= ast_custom_function_register(&realtime_function); res |= ast_custom_function_register(&realtime_store_function); - res |= ast_custom_function_register(&realtime_destroy_function); + res |= ast_custom_function_register_escalating(&realtime_destroy_function, AST_CFE_READ); res |= ast_custom_function_register(&realtimefield_function); res |= ast_custom_function_register(&realtimehash_function); return res; |