; 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.
--- /dev/null
+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.
*/
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 */
/*! \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;
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;
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");
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;
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;