summaryrefslogtreecommitdiff
path: root/funcs/func_realtime.c
diff options
context:
space:
mode:
authorDavid M. Lee <dlee@digium.com>2013-12-16 19:11:51 +0000
committerDavid M. Lee <dlee@digium.com>2013-12-16 19:11:51 +0000
commit744556c01d6e28d4ae46c347f77edfb71778d924 (patch)
treebc90f83b4ec9ef0eafb3d952076bf9ea24406366 /funcs/func_realtime.c
parent00dcee2a640394ac0aae294396d96985c6c1aba1 (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.c62
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;