diff --git a/configs/samples/asterisk.conf.sample b/configs/samples/asterisk.conf.sample index efb33862ae..97f1e7741d 100644 --- a/configs/samples/asterisk.conf.sample +++ b/configs/samples/asterisk.conf.sample @@ -95,10 +95,13 @@ documentation_language = en_US ; Set the language you want documentation ; documented in extensions.conf.sample. ; Default gosub. ;live_dangerously = no ; Enable the execution of 'dangerous' dialplan - ; functions from external sources (AMI, - ; etc.) These functions (such as SHELL) are - ; considered dangerous because they can allow - ; privilege escalation. + ; functions and configuration file access from + ; external sources (AMI, etc.) These functions + ; (such as SHELL) are considered dangerous + ; because they can allow privilege escalation. + ; Configuration files are considered dangerous + ; if they exist outside of the Asterisk + ; configuration directory. ; Default no ;entityid=00:11:22:33:44:55 ; Entity ID. ; This is in the form of a MAC address. diff --git a/doc/UPGRADE-staging/manager_config_live_dangerously.txt b/doc/UPGRADE-staging/manager_config_live_dangerously.txt new file mode 100644 index 0000000000..56f39f9c8d --- /dev/null +++ b/doc/UPGRADE-staging/manager_config_live_dangerously.txt @@ -0,0 +1,8 @@ +Subject: AMI (Asterisk Manager Interface) + +Previously, GetConfig and UpdateConfig were able to access files outside of +the Asterisk configuration directory. Now this access is put behind the +live_dangerously configuration option in asterisk.conf, which is disabled by +default. If access to configuration files outside of the Asterisk configuation +directory is required via AMI, then the live_dangerously configuration option +must be set to yes. diff --git a/include/asterisk/manager.h b/include/asterisk/manager.h index 0c1df60d91..66591c945f 100644 --- a/include/asterisk/manager.h +++ b/include/asterisk/manager.h @@ -350,6 +350,18 @@ void astman_send_list_complete_start(struct mansession *s, const struct message */ void astman_send_list_complete_end(struct mansession *s); +/*! + * \brief Enable/disable the inclusion of 'dangerous' configurations outside + * of the ast_config_AST_CONFIG_DIR + * + * This function can globally enable/disable the loading of configuration files + * outside of ast_config_AST_CONFIG_DIR. + * + * \param new_live_dangerously If true, enable the access of files outside + * ast_config_AST_CONFIG_DIR from astman. + */ +void astman_live_dangerously(int new_live_dangerously); + void __attribute__((format(printf, 2, 3))) astman_append(struct mansession *s, const char *fmt, ...); /*! \brief Determine if a manager session ident is authenticated */ diff --git a/main/manager.c b/main/manager.c index 496e5c1c8a..fc65a33ca4 100644 --- a/main/manager.c +++ b/main/manager.c @@ -1491,6 +1491,11 @@ static struct stasis_forward *rtp_topic_forwarder; /*! \brief The \ref stasis_subscription for forwarding the Security topic to the AMI topic */ static struct stasis_forward *security_topic_forwarder; +/*! + * \brief Set to true (non-zero) to globally allow all dangerous AMI actions to run + */ +static int live_dangerously; + #ifdef TEST_FRAMEWORK /*! \brief The \ref stasis_subscription for forwarding the Test topic to the AMI topic */ static struct stasis_forward *test_suite_forwarder; @@ -3610,6 +3615,29 @@ static int action_ping(struct mansession *s, const struct message *m) return 0; } +void astman_live_dangerously(int new_live_dangerously) +{ + if (new_live_dangerously && !live_dangerously) + { + ast_log(LOG_WARNING, "Manager Configuration load protection disabled.\n"); + } + + if (!new_live_dangerously && live_dangerously) + { + ast_log(LOG_NOTICE, "Manager Configuration load protection enabled.\n"); + } + live_dangerously = new_live_dangerously; +} + +static int restrictedFile(const char *filename) +{ + if (!live_dangerously && !strncasecmp(filename, "/", 1) && + strncasecmp(filename, ast_config_AST_CONFIG_DIR, strlen(ast_config_AST_CONFIG_DIR))) { + return 1; + } + return 0; +} + static int action_getconfig(struct mansession *s, const struct message *m) { struct ast_config *cfg; @@ -3628,6 +3656,11 @@ static int action_getconfig(struct mansession *s, const struct message *m) return 0; } + if (restrictedFile(fn)) { + astman_send_error(s, m, "File requires escalated priveledges"); + return 0; + } + cfg = ast_config_load2(fn, "manager", config_flags); if (cfg == CONFIG_STATUS_FILEMISSING) { astman_send_error(s, m, "Config file not found"); @@ -3755,6 +3788,11 @@ static int action_getconfigjson(struct mansession *s, const struct message *m) return 0; } + if (restrictedFile(fn)) { + astman_send_error(s, m, "File requires escalated priveledges"); + return 0; + } + if (!(cfg = ast_config_load2(fn, "manager", config_flags))) { astman_send_error(s, m, "Config file not found"); return 0; @@ -4106,6 +4144,10 @@ static int action_updateconfig(struct mansession *s, const struct message *m) astman_send_error(s, m, "Filename not specified"); return 0; } + if (restrictedFile(sfn) || restrictedFile(dfn)) { + astman_send_error(s, m, "File requires escalated priveledges"); + return 0; + } if (!(cfg = ast_config_load2(sfn, "manager", config_flags))) { astman_send_error(s, m, "Config file not found"); return 0; diff --git a/main/options.c b/main/options.c index 07afd796d3..1507bc6ba5 100644 --- a/main/options.c +++ b/main/options.c @@ -476,6 +476,7 @@ void load_asterisk_conf(void) } if (!ast_opt_remote) { pbx_live_dangerously(live_dangerously); + astman_live_dangerously(live_dangerously); } option_debug += option_debug_new;