Index: main/manager.c =================================================================== --- main/manager.c (revision 427353) +++ main/manager.c (working copy) @@ -1854,17 +1854,50 @@ { 0, "none" }, }; -/*! \brief Checks to see if a string which can be used to evaluate functions should be rejected */ -static int function_capable_string_allowed_with_auths(const char *evaluating, int writepermlist) +/* Check to see if variable or function name is blacklisted */ +static int check_variable_blacklist(const char *parse) { - if (!(writepermlist & EVENT_FLAG_SYSTEM) - && ( - strstr(evaluating, "SHELL") || /* NoOp(${SHELL(rm -rf /)}) */ - strstr(evaluating, "EVAL") /* NoOp(${EVAL(${some_var_containing_SHELL})}) */ - )) { - return 0; + char *varname = ast_strdupa(parse); + char *data, *data_end; + AST_DECLARE_APP_ARGS(args, + AST_APP_ARG(arg1); + AST_APP_ARG(arg2); + ); + + /* Skip leading underscores */ + if (*varname == '_') { + varname++; + if (*varname == '_') { + varname++; + } } - return 1; + + /* If varname is a function, we want to check the arguments as well */ + if ((data = strchr(varname, '('))) { + *data++ = '\0'; + + if ((data_end = strrchr(data, ')'))) { + *data_end++ = '\0'; + } + AST_STANDARD_APP_ARGS(args, data); + + if (!strcmp(varname, "SHELL") || !strcmp(varname, "EVAL") || !strcmp(varname, "FILE")) { + /* NoOp(${SHELL(rm -rf /)}) + NoOp(${EVAL(${some_var_containing_SHELL})}) + Set(FILE(/path/to/file)=value) */ + return 0; + } else if (!strcmp(varname, "CONFBRIDGE")) { + if (!ast_strlen_zero(args.arg2) && !strncmp(args.arg2, "record_", 7)) { + /* Set(CONFBRIDGE(bridge,record_file)=/path/to/audio/file) */ + return 1; + } + } + } else if (!strcmp(varname, "MONITOR_EXEC")) { + /* Set(MONTIOR_EXEC=rm -rf /) */ + return 1; + } + + return 0; } /*! \brief Convert authority code to a list of options for a user. This will only @@ -4218,6 +4251,12 @@ return 0; } + /* We don't want users with insufficient permissions using certain functions. */ + if (!(s->session->writeperm & EVENT_FLAG_SYSTEM) && check_variable_blacklist(varname)) { + astman_send_error(s, m, "SetVar Access Forbidden: Variable"); + return 0; + } + if (!ast_strlen_zero(name)) { if (!(c = ast_channel_get_by_name(name))) { astman_send_error(s, m, "No such channel"); @@ -4252,7 +4291,7 @@ } /* We don't want users with insufficient permissions using certain functions. */ - if (!(function_capable_string_allowed_with_auths(varname, s->session->writeperm))) { + if (!(s->session->writeperm & EVENT_FLAG_SYSTEM) && check_variable_blacklist(varname)) { astman_send_error(s, m, "GetVar Access Forbidden: Variable"); return 0; } @@ -4414,7 +4453,6 @@ const char *all_chan_variables = astman_get_header(m, "AllVariables"); int all_variables = 0; const char *id = astman_get_header(m, "ActionID"); - char *variables = ast_strdupa(S_OR(chan_variables, "")); struct ast_channel *chan; int channels = 0; int all = ast_strlen_zero(name); /* set if we want all channels */ @@ -4428,9 +4466,19 @@ all_variables = ast_true(all_chan_variables); } - if (!(function_capable_string_allowed_with_auths(variables, s->session->writeperm))) { - astman_send_error(s, m, "Status Access Forbidden: Variables"); - return 0; + if (!ast_strlen_zero(chan_variables)) { + char *parse = ast_strdupa(chan_variables); + int i; + + AST_STANDARD_APP_ARGS(vars, parse); + + for (i = 0; i < vars.argc; i++) { + /* We don't want users with insufficient permissions using certain functions. */ + if (!(s->session->writeperm & EVENT_FLAG_SYSTEM) && check_variable_blacklist(vars.name[i])) { + astman_send_error(s, m, "Status Access Forbidden: Variables"); + return 0; + } + } } if (all) { @@ -4455,10 +4503,6 @@ id_text[0] = '\0'; } - if (!ast_strlen_zero(chan_variables)) { - AST_STANDARD_APP_ARGS(vars, variables); - } - /* if we look by name, we break after the first iteration */ for (; chan; all ? chan = ast_channel_iterator_next(it_chans) : 0) { ast_channel_lock(chan); @@ -4760,7 +4804,7 @@ return 0; } -static int check_blacklist(const char *cmd) +static int check_command_blacklist(const char *cmd) { char *cmd_copy, *cur_cmd; char *cmd_words[MAX_BLACKLIST_CMD_LEN] = { NULL, }; @@ -4810,7 +4854,7 @@ return 0; } - if (check_blacklist(cmd)) { + if (check_command_blacklist(cmd)) { astman_send_error(s, m, "Command blacklisted"); return 0; } @@ -5292,18 +5336,17 @@ /* To run the System application (or anything else that goes to * shell), you must have the additional System privilege */ if (!(s->session->writeperm & EVENT_FLAG_SYSTEM) - && ( - strcasestr(app, "system") || /* System(rm -rf /) - TrySystem(rm -rf /) */ - strcasestr(app, "exec") || /* Exec(System(rm -rf /)) - TryExec(System(rm -rf /)) */ - strcasestr(app, "agi") || /* AGI(/bin/rm,-rf /) - EAGI(/bin/rm,-rf /) */ - strcasestr(app, "mixmonitor") || /* MixMonitor(blah,,rm -rf) */ - strcasestr(app, "externalivr") || /* ExternalIVR(rm -rf) */ - (strstr(appdata, "SHELL") && (bad_appdata = 1)) || /* NoOp(${SHELL(rm -rf /)}) */ - (strstr(appdata, "EVAL") && (bad_appdata = 1)) /* NoOp(${EVAL(${some_var_containing_SHELL})}) */ - )) { + && (!strcasecmp(app, "System") /* System(rm -rf /) */ + || !strcasecmp(app, "TrySystem") /* TrySystem(rm -rf /) */ + || !strcasecmp(app, "Exec") /* Exec(System(rm -rf /)) */ + || !strcasecmp(app, "TryExec") /* TryExec(System(rm -rf /)) */ + || !strcasecmp(app, "AGI") /* AGI(/bin/rm,-rf /) */ + || !strcasecmp(app, "EAGI") /* EAGI(/bin/rm,-rf /) */ + || !strcasecmp(app, "Record") /* Record(/path/to/file) */ + || !strcasecmp(app, "Monitor") /* Set(MONITOR_EXEC=rm -rf /) */ + || !strcasecmp(app, "MixMonitor") /* MixMonitor(,,rm -rf) */ + || !strcasecmp(app, "ExternalIVR") /* ExternalIVR(rm -rf) */ + || (check_variable_blacklist(app) && (bad_appdata = 1)))) { char error_buf[64]; snprintf(error_buf, sizeof(error_buf), "Originate Access Forbidden: %s", bad_appdata ? "Data" : "Application"); astman_send_error(s, m, error_buf);